出不是只能鋪數(shù)據(jù):我用吾碼 V8 做了一張帶公式的審批單)
項目里有一類 Excel 需求第一次聽起來并不復(fù)雜把審批單導(dǎo)出來。真正開始做才發(fā)現(xiàn)它和普通列表導(dǎo)出不是一回事。表頭不止一層標(biāo)題要橫跨整行審批意見左右分欄金額要自動匯總還要控制 A3 橫向打印。繼續(xù)往ExcelData ExcelHeader里塞條件最后通常會得到一段很難維護(hù)的“表格導(dǎo)出特例”。吾碼 V8 的V8.Office.ExportExcel現(xiàn)在有另一條路徑ExcelLayout。它不是圍繞“字段”組織工作簿而是按A1、A1:K15這樣的 Excel 區(qū)域描述值、公式、合并和樣式。我拿官方高級示例做了一次實(shí)際請求也拆開返回的 xlsx 檢查了內(nèi)部結(jié)構(gòu)確認(rèn)這條路線確實(shí)適合審批單、套打表和復(fù)雜報表。列表導(dǎo)出和自由布局解決的不是同一個問題普通業(yè)務(wù)列表的核心是“字段到列”的映射名稱列多寬、金額用什么格式、是否凍結(jié)表頭。此時ExcelData ExcelHeader很順手因為數(shù)據(jù)天然就是一行一條記錄。審批單的核心卻是“這個區(qū)域長什么樣”A1:K1放單據(jù)編號并合并A2:K2放大標(biāo)題A3:K3是明細(xì)表頭D10、F10放匯總公式A11:F11和G11:J11分別放申請人、主管意見A1:K15是固定打印區(qū)域。如果先把這種版式強(qiáng)行轉(zhuǎn)換成字段列表代碼會一直在和數(shù)據(jù)模型較勁。ExcelLayout直接使用 Excel 自己的坐標(biāo)體系反而更接近需求原稿。從源碼也能看出兩種模式不是同一段代碼的參數(shù)差異。ExportExcel發(fā)現(xiàn) Sheet 中存在ExcelLayout后會進(jìn)入WriteExportExcelLayoutSheet先解析每個 Range把樣式、值、公式和數(shù)據(jù)類型累計到單元格狀態(tài)再創(chuàng)建真實(shí)單元格、合并區(qū)域、行列尺寸和打印選項。這里有個我很喜歡的實(shí)現(xiàn)細(xì)節(jié)同一單元格的樣式不是后寫入就整塊替換而是進(jìn)行屬性合并。所以可以先給A1:K15統(tǒng)一畫細(xì)網(wǎng)格再對標(biāo)題、合計和外框做小范圍覆蓋。V8 代碼會短很多也不用為每個單元格重復(fù)寫邊框。一個可以直接改成自己業(yè)務(wù)的最小版本下面這段接口引擎代碼刻意只保留審批單最關(guān)鍵的結(jié)構(gòu)。復(fù)制后改標(biāo)題、明細(xì)數(shù)據(jù)和審批意見就能得到自己的版本。functioncell(list,range,value,style,merge,dataType){varitem{Range:range};if(value!nulltypeofvalue!undefined)item.Valuevalue;if(style)item.Stylestyle;if(mergetrue)item.Mergetrue;if(dataType)item.DataTypedataType;list.push(item);}functionformula(list,range,expression,style){list.push({Range:range,Formula:expression,Style:style});}varcells[];vargrid{FontName:Microsoft YaHei,FontSize:10,VerticalAlignment:Center,BorderStyle:Thin,BorderColor:7F8C9A,WrapText:true};varcenter{HorizontalAlignment:Center,VerticalAlignment:Center};varmoney{HorizontalAlignment:Right,NumberFormat:#,##0.00};// 先處理整塊網(wǎng)格再覆蓋局部樣式cell(cells,A1:H9,null,grid);cell(cells,A1:H1,設(shè)備報廢申請單,{Bold:true,FontSize:18,HorizontalAlignment:Center,BorderTopStyle:Medium,BorderTopColor:34495E},true);varheaders[序號,設(shè)備編號,設(shè)備名稱,數(shù)量,單價,金額,原因,責(zé)任部門];for(vari0;iheaders.length;i){cell(cells,String.fromCharCode(65i)2,headers[i],{Bold:true,BackgroundColor:EEF2F7,HorizontalAlignment:Center});}varrows[[1,EQ-24001,工業(yè)網(wǎng)關(guān),2,1200,null,主板損壞,生產(chǎn)部],[2,EQ-24009,掃碼終端,1,860,null,無法啟動,倉儲部]];for(varr0;rrows.length;r){varexcelRowr3;for(varc0;crows[r].length;c){varstylec3c5?money:center;cell(cells,String.fromCharCode(65c)excelRow,rows[r][c],style);}formula(cells,FexcelRow,DexcelRow*EexcelRow,money);}cell(cells,A6:E6,合計,{Bold:true,HorizontalAlignment:Right},true);formula(cells,F6,SUM(F3:F5),{Bold:true,NumberFormat:#,##0.00});cell(cells,A7:D7,申請人張三已電子簽,{Bold:true},true);cell(cells,E7:H7,主管意見同意已電子簽,{Bold:true},true);cell(cells,A8:H9,說明設(shè)備處置完成后原始審批記錄交財務(wù)歸檔。,{WrapText:true},true);varresultV8.Office.ExportExcel({OsClient:V8.OsClient,ExcelSheets:[{SheetName:設(shè)備報廢申請,ExcelLayout:{Cells:cells,Columns:[{Column:A,Width:8},{Column:B,Width:18},{Column:C,Width:24},{Column:D,Width:10},{Column:E,Width:12},{Column:F,Width:14},{Column:G,Width:22},{Column:H,Width:16}],Rows:[{Row:1,Height:42},{Row:2,Height:30},{Row:8,Height:32},{Row:9,Height:32}]},ExcelOptions:{ShowGridLines:false,FreezeRows:2,PrintOrientation:Landscape,PaperSize:A4,FitToWidth:1,PrintArea:A1:H9,ShowPageNumber:true}}]});if(result.Code!1)returnresult;return{Code:1,Data:{FileName:設(shè)備報廢申請單.xlsx,ContentType:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,FileByteBase64:System.Convert.ToBase64String(result.Data)}};這段代碼有三個容易忽略的點(diǎn)。其一公式單元格不要再寫死結(jié)果。數(shù)量和單價是數(shù)字金額使用D3*E3合計使用SUM(F3:F5)后續(xù)改明細(xì)時計算關(guān)系仍然存在。其二接口引擎必須開啟“響應(yīng)文件”。ExportExcel返回的是字節(jié)數(shù)組只有在 HTTP 返回邊界才轉(zhuǎn)換為 Base64如果只是內(nèi)部繼續(xù)處理沒有必要來回編碼。其三打印參數(shù)應(yīng)和實(shí)際區(qū)域一起設(shè)計。只設(shè)置橫向而不設(shè)置PrintArea、FitToWidth打開文件看著正常打印時仍可能多出空白頁。我實(shí)際驗證到了哪一步2026 年 8 月 4 日我直接請求了吾碼官網(wǎng)文檔給出的高級示例接口GET https://api.itdos.com/apiengine/export-excel-advanced-demo--OsClient--iTdos--接口返回 HTTP 200Content-Type是標(biāo)準(zhǔn) xlsx 類型文件大小為 15,539 字節(jié)文件頭為50 4B 03 04。隨后我按 OOXML 的 ZIP 結(jié)構(gòu)讀取工作簿共有 5 個 Sheet“盤盈虧報廢申請”包含 11 個合并區(qū)域D10、E10、F10分別保存求和、平均和求和公式凍結(jié)窗格落在A4頁面方向為橫向。這能證明線上接口已經(jīng)生成了帶公式、合并、凍結(jié)和打印配置的真實(shí)工作簿而不只是源碼里存在幾個尚未執(zhí)行的方法。邊界也要說清楚本次沒有在不同版本的 Microsoft Excel、WPS、LibreOffice 上逐一做像素級渲染對比因此我不會聲稱所有客戶端的分頁結(jié)果完全一致。真正用于套打時仍應(yīng)該拿目標(biāo)打印機(jī)和客戶使用的 Office 軟件做一次紙張驗收。幾個踩坑點(diǎn)比參數(shù)表更重要Range不要寫成整列或夸張的大區(qū)域。高級布局會為覆蓋區(qū)域創(chuàng)建真實(shí)單元格實(shí)際只用到A1:K15就不要為了省事給A:K整列套樣式。合并區(qū)域不能交叉。A7:D7與E7:H7可以并排但兩塊部分重疊會在生成階段報錯。復(fù)雜模板最好先在紙上或 Excel 中把坐標(biāo)劃清楚再翻譯成 V8 配置。樣式應(yīng)按“公共底色 → 局部覆蓋”組織。先畫網(wǎng)格再處理標(biāo)題、表頭、合計和外框比在每個業(yè)務(wù)單元格里復(fù)制一長串字體與邊框配置更容易維護(hù)。列表和自由布局也不必二選一。一個工作簿的第一張 Sheet 可以用ExcelLayout放審批單第二張 Sheet 繼續(xù)用ExcelData ExcelHeader放完整明細(xì)。對實(shí)際項目來說這往往比把所有信息硬塞進(jìn)一張復(fù)雜表更清楚。我的判斷很簡單需求如果圍繞“字段和記錄”繼續(xù)用標(biāo)準(zhǔn)表格導(dǎo)出需求如果圍繞“區(qū)域和版式”盡早切到ExcelLayout。選對抽象以后復(fù)雜 Excel 反而不再復(fù)雜。參考資料吾碼官方文檔V8 函數(shù)列表 - 后端Microi.Office 的 ExcelLayout 實(shí)現(xiàn)源碼