网友“海”在使用fpspreadsheet时遇到读取复杂的xlsx文件会出错:
经跟踪发现运行到fpspreadsheet\source\common\xlsxooxml.pas的procedure TsSpreadOOXMLReader.ReadFromStream的ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames'))这行出错,查看早期(fpspreadsheet-1.10.1)代码发现这行已注释了的,不清楚新版本为什么又加上这行。
fpspreadsheet-1.10.1版本的:
// process the workbook.xml file (1st run) XMLStream := CreateXMLStream; try if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']); ReadXMLStream(Doc, XMLStream); ReadFileVersion(Doc.DocumentElement.FindNode('fileVersion')); ReadDateMode(Doc.DocumentElement.FindNode('workbookPr')); ReadWorkbookProtection(Doc.DocumentElement.FindNode('workbookProtection')); ReadSheetList(Doc.DocumentElement.FindNode('sheets')); //ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames')); -- don't read here because sheets do not yet exist ReadActiveSheet(Doc.DocumentElement.FindNode('bookViews'), actSheetIndex); FreeAndNil(Doc); finally XMLStream.Free; end;
fpspreadsheet-1.17:
// process the workbook.xml file (1st run) XMLStream := CreateXMLStream; try if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']); ReadXMLStream(Doc, XMLStream); ReadFileVersion(Doc_FindNode('fileVersion')); ReadDateMode(Doc_FindNode('workbookPr')); ReadWorkbookProtection(Doc_FindNode('workbookProtection')); ReadSheetList(Doc_FindNode('sheets')); // This creates the worksheets! ReadRels(AStream, OOXML_PATH_XL_RELS_RELS, FWorkbookRels); ReadSheetRels(AStream); ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames')); ReadActiveSheet(Doc_FindNode('bookViews'), actSheetIndex); FreeAndNil(Doc); finally XMLStream.Free; end;
处理方法:
将这行注释就可以
// process the workbook.xml file (1st run) XMLStream := CreateXMLStream; try if not UnzipToStream(AStream, OOXML_PATH_XL_WORKBOOK, XMLStream) then raise EFPSpreadsheetReader.CreateFmt(rsDefectiveInternalFileStructure, ['xlsx']); ReadXMLStream(Doc, XMLStream); ReadFileVersion(Doc_FindNode('fileVersion')); ReadDateMode(Doc_FindNode('workbookPr')); ReadWorkbookProtection(Doc_FindNode('workbookProtection')); ReadSheetList(Doc_FindNode('sheets')); // This creates the worksheets! ReadRels(AStream, OOXML_PATH_XL_RELS_RELS, FWorkbookRels); ReadSheetRels(AStream); //ReadDefinedNames(Doc.DocumentElement.FindNode('definedNames')); //LBZ 2024-10-25 ReadActiveSheet(Doc_FindNode('bookViews'), actSheetIndex); FreeAndNil(Doc); finally XMLStream.Free; end;
重新编译出现另一个错误:
同样是fpspreadsheet\source\common\xlsxooxml.pas这个文件。
procedure TsSpreadOOXMLReader.ReadPageSetup的StrToInt(s)这的integer超出范围
// First page number s := GetAttrValue(ANode, 'firstPageNumber'); if s <> '' then sheet.PageLayout.StartPageNumber := StrToInt(s);
处理方法很简单:
将StrToInt改为StrToInt64就可以
// First page number s := GetAttrValue(ANode, 'firstPageNumber'); if s <> '' then sheet.PageLayout.StartPageNumber := StrToInt64(s);//lbz 2024-10-25
经上述修改后的fpspreadsheet已能正常读xlsx
分类:
Lazarus
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~