适用背景
1>存有数据的数据库
2>列出需要查找的数据库名+表名的Excel文件
3>需要把MySQL数据库中的大量信息,即不在同一数据库下的若干个表,需要将表中的部分数据或全部数据导出到Excel中,单表对应一个Excel文件,自动创建Excel文件,自动执行。实现自动化解决量化任务的功能。
实现思路
使用Python的openpyxl模块读取已知Excel中存有的需要查找的数据库名+表名 、然后连接数据库,根据读取到的数据库名表名构造Sql语句、从MySQL数据库中按需查找,最后将匹配到的数据写入到新的Excel表中,并保存。
具体如下图
实测无问题,可实现若干个(甚至上千个)非同一数据库下的表导出到Excel的任务,执行速度根据任务大小来定,代码使用循环控制,不会产生过度耗费时间的情况。
注意,已知Excel文件的内容必须按下图规范,若命名非数据库名+“.”+表名,则需要自行修改strrr函数。
表名默认为test.xlsx,执行此代码后,产生的新Excel文件会在同级目录下,建议将此.py文件放在一个文件夹(目录中)执行。
执行代码之前需要确保数据库的连接,关闭test.xlsx文件,防止文件占用报错
A1~An(n为任意整数1,2,…10000…n) 单元格存放数据库名.表名
例如图中第一行school为数据库名,“.”后为表名,sname,ssex,sage为School数据库下student表中的字段名,第二行、第三行、第N行同理。
下图即为test.xlsx
执行代码之前
执行代码之后
新生成的文件命名格式为"数据库名(school)"+“.”+“表名(student)”+"_"+“N(1,2,3…10000…n)”
打开school.student_1展示
附代码如下:此代码用于如上所述情况(将表中部分关键数据根据已知字段名导出)
import openpyxl
import pymysql
from openpyxl import Workbook
# 自定义函数,实现自动创建Excel文件的功能,便于实现
def createexcel(path):
wb = Workbook()
wb.save(path)
# 自定义函数,依此构造新的字符串,用于构造Sql语句
def strrr(li):
a = ""
for i in li:
a = a + i + ','
a = a [:-1]
return a
# 连接数据库 用户名密码修改
conn = pymysql.connect(host="localhost", user="你的数据库用户名", passwd="你的数据库密码",
port=你的数据库端口,默认为3306, charset="utf8")
cur = conn.cursor()
wb = openpyxl.load_workbook('test.xlsx') # 打开存有数据库及表名字段名的EXCEL文件
ws = wb.active
sh = wb.get_sheet_by_name("Sheet1")
row = sh.max_row # 获取Excel最大行数
col = sh.max_column # 获取Excel最大列数
# 使用循环控制语句,执行循环中的内容
for x in range(1,row+1): # x为行数循坏,从1开始递增
db = sh.cell(x,1).value # 读取Excel A列(第一列)中每个单元格的数据,即数据库名.表名
c = [] # 初始化一个空列表,用来存储每个表中的字段名
for y in range(2,col+1): # y为列数循环,从2开始递增,因为各行第一列储存的都是数据库.表信息
if(sh.cell(x, y).value!= None):
column = sh.cell(x,y).value # 此cell(x,y)函数即Excel中的第x行第y列所对应的单元格
c.append(column) # 将从Excel中读取到的表名,依次存储到列表c中
else:
break;
name = db+'_'+str(x)+".xlsx" # 构造字符串用于新建Excel文件的命名,str(x)即为(1,2,3...n)
createexcel(name)
wb1 = openpyxl.load_workbook(name) #打开新创建完成的Excel文件
ws1 = wb1.active
sql = "select x from y;" # 构造Sql语句
sql = sql.replace("x", strrr(c)) # 使用例如sname,ssex,sage等替换x
sql = sql.replace("y", db) # 使用例如school.student替换y,至此,sql语句构造完成
yzz = 65 # 定义一个整数,A所对应的ASCII码值为65
c.reverse() # 将列表c逆序,用于Excel中第一行索引的写入
while c:
ws1[chr(yzz) + '1'] = c.pop() # pop()函数会删除列表中最后一个元素并将值返回,在此将返回的值写入到Excel文件中的A1,B1,C1单元格,对应到上图中的sname,ssex,sage。
yzz += 1 # yzz为定义的整数,初始值65对应A,66对应B,67对应C
cur.execute(sql) # 执行sql语句
table_data = cur.fetchall() # 根据sql语句从MySQL数据库中读取相应数据并将值赋予table_data
j = 1 # 定义整数1用于Excel文件写入,定位到各个单元格
for da in table_data:
y = 65 # 同理于上面的yzz,A对应ASCII值的65
j += 1 # j的初值为1,这里运算过后为2
for k in range(len(da)):
ws1[chr(y) + str(j)] = da[k] # 对应A2,B2,C2等单元格,将数据写入
y += 1
wb1.save(name)
print("数据写入成功")
cur.close()
conn.close()
另一种情况(此代码用于将表中所有数据导出)
下图即为test1.xlsx
可以看到只有A列(第一列)存储数据:数据库名.表名
执行前
执行后
新生成的文件命名格式为"数据库名(school)"+“~”+“表名(student)”+"_"+“N(1,2,3…10000…n)”
打开school.student~1展示
附代码如下:此代码用于将表中所有数据导出
import openpyxl
import pymysql
from openpyxl import Workbook
# 自定义函数,实现自动创建Excel文件的功能,便于实现
def createexcel(path):
wb = Workbook()
wb.save(path)
# 连接数据库 用户名密码修改
conn = pymysql.connect(host="localhost", user="你的数据库用户名", passwd="你的数据库密码",
port=你的数据库端口,默认为3306, charset="utf8")
cur = conn.cursor()
wb = openpyxl.load_workbook('test1.xlsx') # 打开存有数据库及表名字段名的EXCEL文件
ws = wb.active
sh = wb.get_sheet_by_name("Sheet1")
row = sh.max_row # 获取Excel最大行数
col = sh.max_column # 获取Excel最大列数
# 使用循环控制语句,执行循环中的内容
for x in range(1,row+1): # x为行数循坏,从1开始递增
db = sh.cell(x,1).value # 读取Excel A列(第一列)中每个单元格的数据,即数据库名.表名
c = [] # 初始化一个空列表,用来存储每个表中的字段名
for y in range(2,col+1): # y为列数循环,从2开始递增,因为各行第一列储存的都是数据库.表信息
if(sh.cell(x, y).value!= None):
column = sh.cell(x,y).value # 此cell(x,y)函数即Excel中的第x行第y列所对应的单元格
c.append(column) # 将从Excel中读取到的表名,依次存储到列表c中
else:
break;
name = db+'~'+str(x)+".xlsx" # 构造字符串用于新建Excel文件的命名,str(x)即为(1,2,3...n)
createexcel(name)
wb1 = openpyxl.load_workbook(name) #打开新创建完成的Excel文件
ws1 = wb1.active
sql0 = "desc x;"
sql0 = sql0.replace("x",db)
sql = "select * from y;" # 构造Sql语句
sql = sql.replace("y", db) # 使用例如school.student替换y,至此,sql语句构造完成
cur.execute(sql0) # 执行sql语句
table_head = cur.fetchall() # 取表头即索引 sname,ssex之类
for abb in table_head:
c.append(abb[0])
yzz = 65 # 定义一个整数,A所对应的ASCII码值为65
c.reverse() # 将列表c逆序,用于Excel中第一行索引的写入
while c:
ws1[chr(yzz) + '1'] = c.pop() # pop()函数会删除列表中最后一个元素并将值返回,在此将返回的值写入到Excel文件中的A1,B1,C1单元格,对应到上图中的sname,ssex,sage。
yzz += 1 # yzz为定义的整数,初始值65对应A,66对应B,67对应C
cur.execute(sql) # 执行sql语句
table_data = cur.fetchall() # 根据sql语句从MySQL数据库中读取相应数据并将值赋予table_data
j = 1 # 定义整数1用于Excel文件写入,定位到各个单元格
for da in table_data:
y = 65 # 同理于上面的yzz,A对应ASCII值的65
j += 1 # j的初值为1,这里运算过后为2
for k in range(len(da)):
ws1[chr(y) + str(j)] = da[k] # 对应A2,B2,C2等单元格,将数据写入
y += 1
wb1.save(name)
print("数据写入成功")
cur.close()
conn.close()