秋·风

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

网友“海”在使用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

 

posted on 2024-10-25 12:50  秋·风  阅读(83)  评论(0编辑  收藏  举报