diff --git a/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpi b/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpi index ff2ab33cd..98c285969 100644 --- a/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpi +++ b/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpi @@ -1,21 +1,23 @@ + - + - <UseAppBundle Value="False"/> - <ActiveEditorIndexAtStart Value="1"/> </General> <VersionInfo> - <ProjectVersion Value=""/> + <StringTable ProductVersion=""/> </VersionInfo> + <BuildModes Count="1"> + <Item1 Name="default" Default="True"/> + </BuildModes> <PublishOptions> <Version Value="2"/> <IgnoreBinaries Value="False"/> @@ -33,251 +35,30 @@ <PackageName Value="laz_fpspreadsheet"/> </Item1> </RequiredPackages> - <Units Count="14"> + <Units Count="1"> <Unit0> <Filename Value="ooxmlwrite.lpr"/> <IsPartOfProject Value="True"/> <UnitName Value="ooxmlwrite"/> - <CursorPos X="81" Y="57"/> - <TopLine Value="46"/> - <EditorIndex Value="0"/> - <UsageCount Value="309"/> - <Loaded Value="True"/> </Unit0> - <Unit1> - <Filename Value="..\fpolestorage.pas"/> - <UnitName Value="fpolestorage"/> - <CursorPos X="1" Y="1"/> - <TopLine Value="1"/> - <UsageCount Value="18"/> - </Unit1> - <Unit2> - <Filename Value="..\..\..\..\..\lazarus\lcl\interfaces\win32\win32wsstdctrls.pp"/> - <UnitName Value="Win32WSStdCtrls"/> - <CursorPos X="35" Y="720"/> - <TopLine Value="713"/> - <UsageCount Value="75"/> - </Unit2> - <Unit3> - <Filename Value="..\..\..\..\..\lazarus\ideintf\componenteditors.pas"/> - <UnitName Value="ComponentEditors"/> - <CursorPos X="40" Y="332"/> - <TopLine Value="330"/> - <UsageCount Value="73"/> - </Unit3> - <Unit4> - <Filename Value="..\..\xlsbiff5.pas"/> - <UnitName Value="xlsbiff5"/> - <CursorPos X="26" Y="95"/> - <TopLine Value="92"/> - <EditorIndex Value="5"/> - <UsageCount Value="140"/> - <Loaded Value="True"/> - </Unit4> - <Unit5> - <Filename Value="..\..\fpsutils.pas"/> - <UnitName Value="fpsutils"/> - <CursorPos X="1" Y="49"/> - <TopLine Value="30"/> - <EditorIndex Value="4"/> - <UsageCount Value="140"/> - <Loaded Value="True"/> - </Unit5> - <Unit6> - <Filename Value="..\..\xlsbiff2.pas"/> - <UnitName Value="xlsbiff2"/> - <CursorPos X="1" Y="360"/> - <TopLine Value="339"/> - <EditorIndex Value="6"/> - <UsageCount Value="139"/> - <Loaded Value="True"/> - </Unit6> - <Unit7> - <Filename Value="..\..\fpolestorage.pas"/> - <UnitName Value="fpolestorage"/> - <CursorPos X="30" Y="654"/> - <TopLine Value="642"/> - <EditorIndex Value="7"/> - <UsageCount Value="139"/> - <Loaded Value="True"/> - </Unit7> - <Unit8> - <Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\classesh.inc"/> - <CursorPos X="19" Y="562"/> - <TopLine Value="553"/> - <UsageCount Value="40"/> - </Unit8> - <Unit9> - <Filename Value="..\..\..\..\..\lazarus26\fpc\2.2.2\source\rtl\objpas\classes\streams.inc"/> - <CursorPos X="21" Y="158"/> - <TopLine Value="151"/> - <UsageCount Value="40"/> - </Unit9> - <Unit10> - <Filename Value="..\..\fpspreadsheet.pas"/> - <UnitName Value="fpspreadsheet"/> - <CursorPos X="28" Y="26"/> - <TopLine Value="12"/> - <EditorIndex Value="3"/> - <UsageCount Value="95"/> - <Loaded Value="True"/> - </Unit10> - <Unit11> - <Filename Value="..\..\..\..\..\lazarus\lcl\include\customtrayicon.inc"/> - <CursorPos X="22" Y="203"/> - <TopLine Value="197"/> - <UsageCount Value="66"/> - </Unit11> - <Unit12> - <Filename Value="..\..\fpsopendocument.pas"/> - <UnitName Value="fpsopendocument"/> - <CursorPos X="3" Y="296"/> - <TopLine Value="285"/> - <EditorIndex Value="1"/> - <UsageCount Value="13"/> - <Loaded Value="True"/> - </Unit12> - <Unit13> - <Filename Value="..\..\xlsxooxml.pas"/> - <UnitName Value="xlsxooxml"/> - <CursorPos X="1" Y="248"/> - <TopLine Value="244"/> - <EditorIndex Value="2"/> - <UsageCount Value="13"/> - <Loaded Value="True"/> - </Unit13> </Units> - <JumpHistory Count="30" HistoryIndex="29"> - <Position1> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="567" Column="5" TopLine="548"/> - </Position1> - <Position2> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="622" Column="1" TopLine="618"/> - </Position2> - <Position3> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="621" Column="29" TopLine="611"/> - </Position3> - <Position4> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="428" Column="5" TopLine="403"/> - </Position4> - <Position5> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="458" Column="15" TopLine="434"/> - </Position5> - <Position6> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="386" Column="1" TopLine="372"/> - </Position6> - <Position7> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="390" Column="26" TopLine="377"/> - </Position7> - <Position8> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="420" Column="32" TopLine="407"/> - </Position8> - <Position9> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="421" Column="14" TopLine="408"/> - </Position9> - <Position10> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="460" Column="33" TopLine="440"/> - </Position10> - <Position11> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="181" Column="91" TopLine="160"/> - </Position11> - <Position12> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="769" Column="83" TopLine="754"/> - </Position12> - <Position13> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="102" Column="15" TopLine="89"/> - </Position13> - <Position14> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="103" Column="15" TopLine="90"/> - </Position14> - <Position15> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="404" Column="5" TopLine="379"/> - </Position15> - <Position16> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="187" Column="1" TopLine="172"/> - </Position16> - <Position17> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="380" Column="17" TopLine="362"/> - </Position17> - <Position18> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="412" Column="1" TopLine="404"/> - </Position18> - <Position19> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="716" Column="1" TopLine="702"/> - </Position19> - <Position20> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="167" Column="17" TopLine="154"/> - </Position20> - <Position21> - <Filename Value="..\..\xlsbiff2.pas"/> - <Caret Line="69" Column="1" TopLine="57"/> - </Position21> - <Position22> - <Filename Value="ooxmlwrite.lpr"/> - <Caret Line="68" Column="57" TopLine="46"/> - </Position22> - <Position23> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="102" Column="1" TopLine="77"/> - </Position23> - <Position24> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="89" Column="1" TopLine="79"/> - </Position24> - <Position25> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="50" Column="30" TopLine="37"/> - </Position25> - <Position26> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="51" Column="58" TopLine="35"/> - </Position26> - <Position27> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="80" Column="70" TopLine="67"/> - </Position27> - <Position28> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="194" Column="17" TopLine="181"/> - </Position28> - <Position29> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="324" Column="46" TopLine="306"/> - </Position29> - <Position30> - <Filename Value="..\..\xlsxooxml.pas"/> - <Caret Line="211" Column="20" TopLine="188"/> - </Position30> - </JumpHistory> </ProjectOptions> <CompilerOptions> - <Version Value="8"/> + <Version Value="10"/> <PathDelim Value="\"/> <SearchPaths> - <OtherUnitFiles Value="..\"/> - <SrcPath Value="..\"/> + <OtherUnitFiles Value=".."/> + <SrcPath Value=".."/> </SearchPaths> + <Parsing> + <SyntaxOptions> + <UseAnsiStrings Value="False"/> + </SyntaxOptions> + </Parsing> <Other> + <CompilerMessages> + <UseMsgFile Value="True"/> + </CompilerMessages> <CompilerPath Value="$(CompPath)"/> </Other> </CompilerOptions> diff --git a/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpr b/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpr index a05dfc6e2..8a43892d9 100644 --- a/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpr +++ b/components/fpspreadsheet/examples/ooxmldemo/ooxmlwrite.lpr @@ -15,7 +15,6 @@ uses var MyWorkbook: TsWorkbook; MyWorksheet: TsWorksheet; - MyFormula: TRPNFormula; MyDir: string; i: Integer; a: TStringList; diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index f01e73e4b..16c519d19 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -190,6 +190,8 @@ type { Base methods } constructor Create; destructor Destroy; override; + { Utils } + class function CellPosToText(ARow, ACol: Cardinal): string; { Data manipulation methods } function FindCell(ARow, ACol: Cardinal): PCell; function GetCell(ARow, ACol: Cardinal): PCell; @@ -388,6 +390,19 @@ begin inherited Destroy; end; +{@@ Converts a FPSpreadsheet cell position, which is Row, Col in numbers + and zero based, to a textual representation which is [Col][Row], + being that the Col is in letters and the row is in 1-based numbers } +class function TsWorksheet.CellPosToText(ARow, ACol: Cardinal): string; +var + lStr: string; +begin + lStr := ''; + if ACol < 26 then lStr := Char(ACol+54); + + Result := Format('%s%d', [lStr, ARow+1]); +end; + {@@ Tryes to locate a Cell in the list of already written Cells diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas index a07f71224..12a32b772 100755 --- a/components/fpspreadsheet/xlsxooxml.pas +++ b/components/fpspreadsheet/xlsxooxml.pas @@ -32,6 +32,7 @@ interface uses Classes, SysUtils, fpszipper, {NOTE: fpszipper is the latest zipper.pp Change to standard zipper when FPC 2.4 is released } + {xmlread, DOM,} AVL_Tree, fpspreadsheet; type @@ -51,6 +52,7 @@ type FSRelsRels: TStringStream; FSWorkbook, FSWorkbookRels, FSStyles, FSSharedStrings: TStringStream; FSSheets: array of TStringStream; + FCurSheetNum: Integer; { Routines to write those files } procedure WriteGlobalFiles; procedure WriteContent(AData: TsWorkbook); @@ -244,48 +246,99 @@ begin '</sst>'; end; +{ +FSheets[CurStr] := + XML_HEADER + LineEnding + + '<worksheet xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding + + ' <sheetViews>' + LineEnding + + ' <sheetView workbookViewId="0" />' + LineEnding + + ' </sheetViews>' + LineEnding + + ' <sheetData>' + LineEnding + + ' <row r="1" spans="1:4">' + LineEnding + + ' <c r="A1">' + LineEnding + + ' <v>1</v>' + LineEnding + + ' </c>' + LineEnding + + ' <c r="B1">' + LineEnding + + ' <v>2</v>' + LineEnding + + ' </c>' + LineEnding + + ' <c r="C1">' + LineEnding + + ' <v>3</v>' + LineEnding + + ' </c>' + LineEnding + + ' <c r="D1">' + LineEnding + + ' <v>4</v>' + LineEnding + + ' </c>' + LineEnding + + ' </row>' + LineEnding + + ' <row r="2" spans="1:4">' + LineEnding + + ' <c r="A2" t="s">' + LineEnding + + ' <v>0</v>' + LineEnding + + ' </c>' + LineEnding + + ' <c r="B2" t="s">' + LineEnding + + ' <v>1</v>' + LineEnding + + ' </c>' + LineEnding + + ' <c r="C2" t="s">' + LineEnding + + ' <v>2</v>' + LineEnding + + ' </c>' + LineEnding + + ' <c r="D2" t="s">' + LineEnding + + ' <v>3</v>' + LineEnding + + ' </c>' + LineEnding + + ' </row>' + LineEnding + + ' </sheetData>' + LineEnding + + '</worksheet>'; +} procedure TsSpreadOOXMLWriter.WriteWorksheet(CurSheet: TsWorksheet); var - CurStr: Integer; + j, k: Integer; + CurCell: PCell; + CurRow: array of PCell; + LastColNum: Cardinal; + LCell: TCell; + AVLNode: TAVLTreeNode; + CellPosText: string; begin - CurStr := Length(FSheets); - SetLength(FSheets, CurStr + 1); + FCurSheetNum := Length(FSheets); + SetLength(FSheets, FCurSheetNum + 1); - FSheets[CurStr] := + LastColNum := CurSheet.GetLastColNumber; + + // Header + FSheets[FCurSheetNum] := XML_HEADER + LineEnding + '<worksheet xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding + ' <sheetViews>' + LineEnding + ' <sheetView workbookViewId="0" />' + LineEnding + ' </sheetViews>' + LineEnding + - ' <sheetData>' + LineEnding + - ' <row r="1" spans="1:4">' + LineEnding + - ' <c r="A1">' + LineEnding + - ' <v>1</v>' + LineEnding + - ' </c>' + LineEnding + - ' <c r="B1">' + LineEnding + - ' <v>2</v>' + LineEnding + - ' </c>' + LineEnding + - ' <c r="C1">' + LineEnding + - ' <v>3</v>' + LineEnding + - ' </c>' + LineEnding + - ' <c r="D1">' + LineEnding + - ' <v>4</v>' + LineEnding + - ' </c>' + LineEnding + - ' </row>' + LineEnding + - ' <row r="2" spans="1:4">' + LineEnding + - ' <c r="A2" t="s">' + LineEnding + - ' <v>0</v>' + LineEnding + - ' </c>' + LineEnding + - ' <c r="B2" t="s">' + LineEnding + - ' <v>1</v>' + LineEnding + - ' </c>' + LineEnding + - ' <c r="C2" t="s">' + LineEnding + - ' <v>2</v>' + LineEnding + - ' </c>' + LineEnding + - ' <c r="D2" t="s">' + LineEnding + - ' <v>3</v>' + LineEnding + - ' </c>' + LineEnding + - ' </row>' + LineEnding + + ' <sheetData>' + LineEnding; + + // The cells need to be written in order, row by row, cell by cell + for j := 0 to CurSheet.GetLastRowNumber do + begin + FSheets[FCurSheetNum] := FSheets[FCurSheetNum] + + Format(' <row r="%d" spans="1:%d">', [j+1,LastColNum+1]) + LineEnding; + + // Write cells from this row. + for k := 0 to LastColNum do + begin + LCell.Row := j; + LCell.Col := k; + AVLNode := CurSheet.Cells.Find(@LCell); + if Assigned(AVLNode) then + WriteCellCallback(PCell(AVLNode.Data), nil) + else + begin + CellPosText := CurSheet.CellPosToText(j, k); + FSheets[FCurSheetNum] := FSheets[FCurSheetNum] + + Format(' <c r="%s">', [CellPosText]) + LineEnding + + ' <v></v>' + LineEnding + + ' </c>' + LineEnding; + end; + end; + + FSheets[FCurSheetNum] := FSheets[FCurSheetNum] + + ' </row>' + LineEnding; + end; + + // Footer + FSheets[FCurSheetNum] := FSheets[FCurSheetNum] + ' </sheetData>' + LineEnding + '</worksheet>'; end; @@ -383,8 +436,14 @@ end; } procedure TsSpreadOOXMLWriter.WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string; ACell: PCell); +var + CellPosText: string; begin - + CellPosText := TsWorksheet.CellPosToText(ARow, ACol); + FSheets[FCurSheetNum] := FSheets[FCurSheetNum] + + Format(' <c r="%s" t="s">', [CellPosText]) + LineEnding + + ' <v>2</v>' + LineEnding + + ' </c>' + LineEnding; end; { @@ -392,8 +451,14 @@ end; } procedure TsSpreadOOXMLWriter.WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double; ACell: PCell); +var + CellPosText: String; begin - + CellPosText := TsWorksheet.CellPosToText(ARow, ACol); + FSheets[FCurSheetNum] := FSheets[FCurSheetNum] + + Format(' <c r="%s">', [CellPosText]) + LineEnding + + ' <v>1</v>' + LineEnding + + ' </c>' + LineEnding; end; {