华泰证券0412-0612-按年.xlsx 文件中保存了所有股票交易记录,例如:这样的记录:
编写python程序,现在从中提取,一个股票一个SHEET页面,存放这个股票所有的交易记录
把所有无法提取,或者异常记录都保存到一个 异常 sheet页面中
输出 整理.xlsx
把一个按年份分sheet 的股票交易流水文件(比如2004年一个sheet、2005年一个sheet......),重新整理成按股票分sheet的新文件(兰州铝业一个sheet、四川长虹一个sheet......),异常数据单独放一个"异常"sheet。
import pandas as pd
import openpyxl
from openpyxl.utils import get_column_letter
INPUT_FILE = "华泰证券0412-0612-按年.xlsx"
OUTPUT_FILE = "整理.xlsx"
def main():
xl = pd.ExcelFile(INPUT_FILE)
all_dfs = \[\]
for sheet_name in xl.sheet_names:
df = pd.read_excel(INPUT_FILE, sheet_name=sheet_name, dtype=str)
df'_源SHEET' = sheet_name
all_dfs.append(df)
data = pd.concat(all_dfs, ignore_index=True)
所有单元格内容 trim 一下
try:
data = data.map(lambda v: v.strip() if isinstance(v, str) else v)
except AttributeError:
data = data.applymap(lambda v: v.strip() if isinstance(v, str) else v)
data.columns = str(c).strip() for c in data.columns
expected_cols = '日期', '币种', '股票名称', '股票代码', '业务标志', '发生数量', '成交均', '收付金额', '资金余额'
if '成交均价' in data.columns and '成交均' not in data.columns:
data = data.rename(columns={'成交均价': '成交均'})
for c in expected_cols:
if c not in data.columns:
datac = None
数字列转为数值类型
int_cols = '发生数量'
float_cols = '成交均', '收付金额', '资金余额'
for c in int_cols + float_cols:
datac = pd.to_numeric(datac, errors='coerce')
for c in int_cols:
datac = datac.astype('Int64')
normal_rows = \[\]
abnormal_rows = \[\]
for idx, row in data.iterrows():
code = row.get('股票代码')
name = row.get('股票名称')
date = row.get('日期')
if pd.isna(code) or code == '' or pd.isna(name) or name == '' or pd.isna(date) or date == '':
abnormal_rows.append(row)
else:
normal_rows.append(row)
数字格式
int_fmt = '0'
float_fmt = '0.00'
def apply_number_format(ws, cols):
header = cell.value for cell in ws\[1]
for col_idx, col_name in enumerate(header, 1):
if col_name in int_cols:
fmt = int_fmt
elif col_name in float_cols:
fmt = float_fmt
else:
continue
for row_cells in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx):
for cell in row_cells:
cell.number_format = fmt
with pd.ExcelWriter(OUTPUT_FILE, engine='openpyxl') as writer:
used_names = set()
if normal_rows:
normal_df = pd.DataFrame(normal_rows)
for name, grp in normal_df.groupby('股票名称'):
sheet_name = str(name)
for ch in '/', '\\\\', '?', '\*', '\[', '', ':']:
sheet_name = sheet_name.replace(ch, '_')
sheet_name = sheet_name:31
base = sheet_name
cnt = 1
while sheet_name in used_names:
cnt += 1
suffix = f"_{cnt}"
sheet_name = (base:31-len(suffix)) + suffix
used_names.add(sheet_name)
正常页:只输出标准列,不包含 _源SHEET
out = grpexpected_cols.copy()
out = out.sort_values(by='日期', key=lambda s: s.astype(str))
out.to_excel(writer, sheet_name=sheet_name, index=False)
异常页:包含 _源SHEET 列
if abnormal_rows:
ab_df = pd.DataFrame(abnormal_rows)
ab_cols = expected_cols + '_源SHEET'
ab_cols = c for c in ab_cols if c in ab_df.columns
ab_dfab_cols.to_excel(writer, sheet_name='异常', index=False)
else:
pd.DataFrame(columns=expected_cols).to_excel(writer, sheet_name='异常', index=False)
设置列宽 + 数字格式
wb = openpyxl.load_workbook(OUTPUT_FILE)
for ws in wb.worksheets:
apply_number_format(ws, expected_cols)
for col_idx, col_cells in enumerate(ws.columns, 1):
max_len = 0
for cell in col_cells:
if cell.value is not None:
l = len(str(cell.value))
if l > max_len:
max_len = l
ws.column_dimensionsget_column_letter(col_idx).width = min(max_len + 2, 30)
wb.save(OUTPUT_FILE)
print(f"完成!输出文件:{OUTPUT_FILE}")
print(f"正常记录:{len(normal_rows)}, 异常记录:{len(abnormal_rows)}")
print(f"股票 sheet 数:{len(wb.sheetnames) - 1}")
if name == 'main':
main()