From f192a7a302373ae931104d6cb44076fe694da470 Mon Sep 17 00:00:00 2001 From: zhangxiao <898441624@qq.com> Date: 星期三, 16 十月 2024 14:53:32 +0800 Subject: [PATCH] 报表合并 --- .gitignore | 1 app/api/excel.py | 105 +++++++++++++++++++++++++++++++++++ main.py | 2 app/utils/excelmerge/conformity.py | 64 +++++++++++++++++++++ app/utils/excelmerge/国网上海电力整合模版.xlsx | 0 5 files changed, 172 insertions(+), 0 deletions(-) diff --git a/.gitignore b/.gitignore index 7836932..cba8701 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ venv dist +data build main __pycache__ diff --git a/app/api/excel.py b/app/api/excel.py new file mode 100644 index 0000000..78a5e03 --- /dev/null +++ b/app/api/excel.py @@ -0,0 +1,105 @@ +from fastapi import APIRouter, File, UploadFile +from fastapi.responses import JSONResponse, FileResponse +from fastapi.exceptions import HTTPException +from werkzeug.utils import secure_filename +from app.utils.excelmerge.conformity import run_conformity +from pathlib import Path +import subprocess +import shutil +import os + + +router = APIRouter() + +ALLOWED_EXTENSIONS = {'xlsx'} +EXCEL_FILES_PATH = 'data/output' +SOURCE_FILES_PATH = 'data/source' +output_path_value = None + + +def allowed_file(filename): + return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS + + +def create_dir_if_not_exists(path): + if not os.path.exists(path): + os.makedirs(path) + + +@router.post('/excel/upload') +async def upload_file(files: list[UploadFile] = File(...)): + if not any(file.filename for file in files): + return JSONResponse(content={"error": "娌℃湁鏂囦欢閮ㄥ垎"}, status_code=400) + + create_dir_if_not_exists(SOURCE_FILES_PATH) + + # 娓呯┖SOURCE_FILES_PATH鐩綍 + for filename in os.listdir(SOURCE_FILES_PATH): + file_path = os.path.join(SOURCE_FILES_PATH, filename) + try: + if os.path.isfile(file_path) or os.path.islink(file_path): + os.unlink(file_path) + elif os.path.isdir(file_path): + shutil.rmtree(file_path) + except Exception as e: + return JSONResponse(content={"error": "鏂囦欢澶勭悊鍑洪敊"}, status_code=500) + + save_path_list = [] + for file in files: + if file.filename == '': + return JSONResponse(content={"error": "娌℃湁閫夋嫨鏂囦欢"}, status_code=400) + if file and allowed_file(file.filename): + filename = secure_filename(file.filename) + save_path = os.path.join(SOURCE_FILES_PATH, filename) + with open(save_path, 'wb') as buffer: + shutil.copyfileobj(file.file, buffer) + save_path_list.append(save_path) + else: + return JSONResponse(content={"error": "涓嶅厑璁哥殑鏂囦欢绫诲瀷"}, status_code=400) + return JSONResponse(content={"message": "鏂囦欢涓婁紶鎴愬姛", "paths": save_path_list}, status_code=201) + + +@router.post('/excel/conformity') +async def run_conformity_api(): + global output_path_value # 澹版槑鍏ㄥ眬鍙橀噺 + try: + create_dir_if_not_exists(EXCEL_FILES_PATH) + + # 娓呯┖EXCEL_FILES_PATH鐩綍 + for filename in os.listdir(EXCEL_FILES_PATH): + file_path = os.path.join(EXCEL_FILES_PATH, filename) + try: + if os.path.isfile(file_path) or os.path.islink(file_path): + os.unlink(file_path) + elif os.path.isdir(file_path): + shutil.rmtree(file_path) + except Exception as e: + return JSONResponse(content={"error": "鏂囦欢澶勭悊鍑洪敊"}, status_code=500) + + # 杩愯鏂规硶 + output_path = run_conformity() + output_path_value = output_path + return JSONResponse(content={"message": "conformity.py 杩愯鎴愬姛", "output_path": str(output_path)}, status_code=200) + except Exception as e: + return JSONResponse(content={"error": str(e)}, status_code=500) + + +@router.get('/excel/file/status') +async def get_file_status(): + try: + return JSONResponse(content={"output_path": str(output_path_value)}, status_code=200) + except Exception as e: + return JSONResponse(content={"error": str(e)}, status_code=500) + + +@router.get('/excel/download_excel') +async def download_excel(): + try: + files = os.listdir(EXCEL_FILES_PATH) + first_file = files[0] + return FileResponse(os.path.join(EXCEL_FILES_PATH, first_file), filename=first_file, + media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + except FileNotFoundError: + raise HTTPException(status_code=404, detail="鏂囦欢涓嶅瓨鍦�") + except Exception as e: + raise HTTPException(status_code=500, detail="鏈嶅姟鍣ㄩ敊璇�") \ No newline at end of file diff --git a/app/utils/excelmerge/conformity.py b/app/utils/excelmerge/conformity.py new file mode 100644 index 0000000..901357c --- /dev/null +++ b/app/utils/excelmerge/conformity.py @@ -0,0 +1,64 @@ +import xlwings as xw +from datetime import datetime +import os +import shutil + + +def run_conformity(): + + source_folder = os.path.join('data', 'source') + template_path = os.path.join('app', 'utils', 'excelmerge', '鍥界綉涓婃捣鐢靛姏鏁村悎妯$増.xlsx') + EXCEL_FILES_PATH = os.path.join('data', 'output') + + app = xw.App(visible=False) + templateExcel = xw.Book(template_path) + + sheet1 = templateExcel.sheets['鎶�鏈洃鐫e伐浣滅粺璁¤〃'] + sheet2 = templateExcel.sheets['鎶�鏈洃鐫e憡锛堥锛夎鍗曠粺璁¤〃'] + sheet3 = templateExcel.sheets['鎶曚骇鍓嶆妧鏈洃鐫f姤鍛婄粺璁¤〃'] + sheet4 = templateExcel.sheets['鎶�鏈洃鐫g粏鍒欏畬鍠勫缓璁�'] + sheet5 = templateExcel.sheets['鍏稿瀷缁忛獙浜ゆ祦'] + + source_files = [f for f in os.listdir(source_folder) if f.endswith('.xlsx') and not f.startswith('~$')] + + for file in source_files: + sourceExcel = xw.Book(os.path.join(source_folder, file)) + ssheet1 = sourceExcel.sheets['鎶�鏈洃鐫e伐浣滅粺璁¤〃'] + ssheet2 = sourceExcel.sheets['鎶�鏈洃鐫e憡锛堥锛夎鍗曠粺璁¤〃'] + ssheet3 = sourceExcel.sheets['鎶曚骇鍓嶆妧鏈洃鐫f姤鍛婄粺璁¤〃'] + ssheet4 = sourceExcel.sheets['鎶�鏈洃鐫g粏鍒欏畬鍠勫缓璁�'] + ssheet5 = sourceExcel.sheets['鍏稿瀷缁忛獙浜ゆ祦'] + for ssheet in [ssheet1, ssheet2, ssheet3, ssheet4, ssheet5]: + last_row_value = ssheet.range(f'A{ssheet.used_range.rows.count}').value + if isinstance(last_row_value, str): + ssheet.range(f'A{ssheet.used_range.rows.count}:AA{ssheet.used_range.rows.count}').delete() + for (ssheet, tsheet, start_point) in [ + (ssheet1, sheet1, 4), + (ssheet2, sheet2, 3), + (ssheet3, sheet3, 3), + (ssheet4, sheet4, 4), + (ssheet5, sheet5, 3), + ]: + for row in range(start_point, ssheet.used_range.rows.count + 1): + a_cell_value = ssheet.range(f'A{row}').value + if not isinstance(a_cell_value, (int, float)): + continue + if not all(cell.value is None or cell.value == '' for cell in ssheet.range(f'B{row}:AA{row}')): + tsheet.range(f'B{tsheet.used_range.rows.count + 1}').value = ssheet.range(f'B{row}:AA{row}').value + sourceExcel.close() + for tsheet, start_point in [(sheet1, 4), (sheet2, 3), (sheet3, 3), (sheet4, 4), (sheet5, 3)]: + last_row = tsheet.used_range.rows.count + number = 1 + for i in range(start_point, last_row + 1): + tsheet.range(f'A{i}').value = number + number += 1 + + timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + output_path = os.path.join(EXCEL_FILES_PATH, f'{timestamp}.xlsx') + templateExcel.save(output_path) + templateExcel.close() + app.quit() + + return timestamp + + diff --git "a/app/utils/excelmerge/\345\233\275\347\275\221\344\270\212\346\265\267\347\224\265\345\212\233\346\225\264\345\220\210\346\250\241\347\211\210.xlsx" "b/app/utils/excelmerge/\345\233\275\347\275\221\344\270\212\346\265\267\347\224\265\345\212\233\346\225\264\345\220\210\346\250\241\347\211\210.xlsx" new file mode 100644 index 0000000..d7c7e52 --- /dev/null +++ "b/app/utils/excelmerge/\345\233\275\347\275\221\344\270\212\346\265\267\347\224\265\345\212\233\346\225\264\345\220\210\346\250\241\347\211\210.xlsx" Binary files differ diff --git a/main.py b/main.py index d5a8c5d..70d19c0 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ from app.api.auth import router as auth_router from app.api.chat import router as chat_router from app.api.agent import router as agent_router +from app.api.excel import router as excel_router from app.models.base_model import init_db init_db() @@ -14,6 +15,7 @@ app.include_router(auth_router, prefix='/auth', tags=["auth"]) app.include_router(chat_router, prefix='/chat', tags=["chat"]) app.include_router(agent_router, prefix='/agent', tags=["agent"]) +app.include_router(excel_router, prefix='/document', tags=["document"]) if __name__ == "__main__": import uvicorn -- Gitblit v1.8.0