fpspreadsheet: Improves OpenDocument support

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@692 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2009-02-02 09:58:51 +00:00
parent 8e0524517b
commit 933d8a5b44
16 changed files with 2386 additions and 580 deletions

View File

@ -33,13 +33,13 @@
<PackageName Value="laz_fpspreadsheet"/> <PackageName Value="laz_fpspreadsheet"/>
</Item1> </Item1>
</RequiredPackages> </RequiredPackages>
<Units Count="12"> <Units Count="14">
<Unit0> <Unit0>
<Filename Value="excel5write.lpr"/> <Filename Value="excel5write.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="excel5write"/> <UnitName Value="excel5write"/>
<CursorPos X="35" Y="56"/> <CursorPos X="3" Y="17"/>
<TopLine Value="46"/> <TopLine Value="1"/>
<EditorIndex Value="0"/> <EditorIndex Value="0"/>
<UsageCount Value="309"/> <UsageCount Value="309"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -68,8 +68,8 @@
<Unit4> <Unit4>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<UnitName Value="xlsbiff5"/> <UnitName Value="xlsbiff5"/>
<CursorPos X="1" Y="224"/> <CursorPos X="33" Y="539"/>
<TopLine Value="215"/> <TopLine Value="526"/>
<EditorIndex Value="3"/> <EditorIndex Value="3"/>
<UsageCount Value="140"/> <UsageCount Value="140"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -86,9 +86,9 @@
<Unit6> <Unit6>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/> <UnitName Value="xlsbiff2"/>
<CursorPos X="1" Y="69"/> <CursorPos X="34" Y="256"/>
<TopLine Value="57"/> <TopLine Value="236"/>
<EditorIndex Value="4"/> <EditorIndex Value="6"/>
<UsageCount Value="139"/> <UsageCount Value="139"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit6> </Unit6>
@ -97,7 +97,7 @@
<UnitName Value="fpolestorage"/> <UnitName Value="fpolestorage"/>
<CursorPos X="30" Y="654"/> <CursorPos X="30" Y="654"/>
<TopLine Value="642"/> <TopLine Value="642"/>
<EditorIndex Value="5"/> <EditorIndex Value="7"/>
<UsageCount Value="139"/> <UsageCount Value="139"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit7> </Unit7>
@ -116,8 +116,8 @@
<Unit10> <Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/> <UnitName Value="fpspreadsheet"/>
<CursorPos X="40" Y="137"/> <CursorPos X="1" Y="13"/>
<TopLine Value="129"/> <TopLine Value="12"/>
<EditorIndex Value="1"/> <EditorIndex Value="1"/>
<UsageCount Value="92"/> <UsageCount Value="92"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -128,108 +128,146 @@
<TopLine Value="197"/> <TopLine Value="197"/>
<UsageCount Value="67"/> <UsageCount Value="67"/>
</Unit11> </Unit11>
<Unit12>
<Filename Value="..\..\fpsopendocument.pas"/>
<UnitName Value="fpsopendocument"/>
<CursorPos X="20" Y="383"/>
<TopLine Value="369"/>
<EditorIndex Value="4"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit12>
<Unit13>
<Filename Value="..\..\xlsbiff8.pas"/>
<UnitName Value="xlsbiff8"/>
<CursorPos X="34" Y="339"/>
<TopLine Value="317"/>
<EditorIndex Value="5"/>
<UsageCount Value="10"/>
<Loaded Value="True"/>
</Unit13>
</Units> </Units>
<JumpHistory Count="25" HistoryIndex="24"> <JumpHistory Count="30" HistoryIndex="29">
<Position1> <Position1>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="40" Column="5" TopLine="31"/> <Caret Line="405" Column="5" TopLine="386"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="472" Column="49" TopLine="461"/> <Caret Line="404" Column="14" TopLine="401"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="405" Column="5" TopLine="386"/> <Caret Line="79" Column="42" TopLine="72"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="404" Column="14" TopLine="401"/> <Caret Line="78" Column="31" TopLine="67"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="79" Column="42" TopLine="72"/> <Caret Line="314" Column="39" TopLine="296"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="31" TopLine="67"/> <Caret Line="479" Column="1" TopLine="469"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="314" Column="39" TopLine="296"/> <Caret Line="470" Column="1" TopLine="460"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="479" Column="1" TopLine="469"/>
</Position8>
<Position9>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="470" Column="1" TopLine="460"/>
</Position9>
<Position10>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="217" Column="3" TopLine="205"/> <Caret Line="217" Column="3" TopLine="205"/>
</Position10> </Position8>
<Position11> <Position9>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="218" Column="23" TopLine="208"/> <Caret Line="218" Column="23" TopLine="208"/>
</Position9>
<Position10>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="10" TopLine="66"/>
</Position10>
<Position11>
<Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="375" Column="1" TopLine="367"/>
</Position11> </Position11>
<Position12> <Position12>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="78" Column="10" TopLine="66"/> <Caret Line="76" Column="17" TopLine="65"/>
</Position12> </Position12>
<Position13> <Position13>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="375" Column="1" TopLine="367"/> <Caret Line="363" Column="1" TopLine="357"/>
</Position13> </Position13>
<Position14> <Position14>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="76" Column="17" TopLine="65"/> <Caret Line="77" Column="7" TopLine="76"/>
</Position14> </Position14>
<Position15> <Position15>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="363" Column="1" TopLine="357"/> <Caret Line="137" Column="40" TopLine="129"/>
</Position15> </Position15>
<Position16> <Position16>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="77" Column="7" TopLine="76"/> <Caret Line="563" Column="5" TopLine="544"/>
</Position16> </Position16>
<Position17> <Position17>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="137" Column="40" TopLine="129"/> <Caret Line="486" Column="5" TopLine="467"/>
</Position17> </Position17>
<Position18> <Position18>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="563" Column="5" TopLine="544"/> <Caret Line="510" Column="5" TopLine="491"/>
</Position18> </Position18>
<Position19> <Position19>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="486" Column="5" TopLine="467"/> <Caret Line="94" Column="46" TopLine="84"/>
</Position19> </Position19>
<Position20> <Position20>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="510" Column="5" TopLine="491"/> <Caret Line="686" Column="5" TopLine="667"/>
</Position20> </Position20>
<Position21> <Position21>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="94" Column="46" TopLine="84"/> <Caret Line="567" Column="5" TopLine="548"/>
</Position21> </Position21>
<Position22> <Position22>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="686" Column="5" TopLine="667"/> <Caret Line="622" Column="1" TopLine="618"/>
</Position22> </Position22>
<Position23> <Position23>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="567" Column="5" TopLine="548"/> <Caret Line="621" Column="29" TopLine="611"/>
</Position23> </Position23>
<Position24> <Position24>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="622" Column="1" TopLine="618"/> <Caret Line="100" Column="17" TopLine="92"/>
</Position24> </Position24>
<Position25> <Position25>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="621" Column="29" TopLine="611"/> <Caret Line="615" Column="34" TopLine="593"/>
</Position25> </Position25>
<Position26>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position26>
<Position27>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="56" Column="88" TopLine="43"/>
</Position27>
<Position28>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position28>
<Position29>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="69" Column="88" TopLine="56"/>
</Position29>
<Position30>
<Filename Value="excel5write.lpr"/>
<Caret Line="47" Column="30" TopLine="33"/>
</Position30>
</JumpHistory> </JumpHistory>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -15,10 +15,9 @@ uses
var var
MyWorkbook: TsWorkbook; MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet; MyWorksheet: TsWorksheet;
MyFormula: TRPNFormula; MyFormula: TsFormula;
MyDir: string; MyDir: string;
i: Integer; i: Integer;
a: TStringList;
begin begin
// Open the output file // Open the output file
MyDir := ExtractFilePath(ParamStr(0)); MyDir := ExtractFilePath(ParamStr(0));
@ -44,16 +43,8 @@ begin
} }
// Write the formula E1 = A1 + B1 // Write the formula E1 = A1 + B1
// or, in RPN: A1, B1, + // MyFormula.FormulaStr := '';
SetLength(MyFormula, 3); // MyWorksheet.WriteFormula(0, 4, MyFormula);
MyFormula[0].TokenID := INT_EXCEL_TOKEN_TREFV; {A1}
MyFormula[0].Col := 0;
MyFormula[0].Row := 0;
MyFormula[1].TokenID := INT_EXCEL_TOKEN_TREFV; {B1}
MyFormula[1].Col := 1;
MyFormula[1].Row := 0;
MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; {+}
MyWorksheet.WriteRPNFormula(0, 4, MyFormula);
// Creates a new worksheet // Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2'); MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');

View File

@ -11,7 +11,7 @@
<TargetFileExt Value=".exe"/> <TargetFileExt Value=".exe"/>
<Title Value="ooxmlwrite"/> <Title Value="ooxmlwrite"/>
<UseAppBundle Value="False"/> <UseAppBundle Value="False"/>
<ActiveEditorIndexAtStart Value="2"/> <ActiveEditorIndexAtStart Value="1"/>
</General> </General>
<VersionInfo> <VersionInfo>
<ProjectVersion Value=""/> <ProjectVersion Value=""/>
@ -38,8 +38,8 @@
<Filename Value="ooxmlwrite.lpr"/> <Filename Value="ooxmlwrite.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="ooxmlwrite"/> <UnitName Value="ooxmlwrite"/>
<CursorPos X="19" Y="46"/> <CursorPos X="81" Y="57"/>
<TopLine Value="33"/> <TopLine Value="46"/>
<EditorIndex Value="0"/> <EditorIndex Value="0"/>
<UsageCount Value="309"/> <UsageCount Value="309"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -131,8 +131,8 @@
<Unit12> <Unit12>
<Filename Value="..\..\fpsopendocument.pas"/> <Filename Value="..\..\fpsopendocument.pas"/>
<UnitName Value="fpsopendocument"/> <UnitName Value="fpsopendocument"/>
<CursorPos X="15" Y="1"/> <CursorPos X="3" Y="296"/>
<TopLine Value="1"/> <TopLine Value="285"/>
<EditorIndex Value="1"/> <EditorIndex Value="1"/>
<UsageCount Value="13"/> <UsageCount Value="13"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -140,8 +140,8 @@
<Unit13> <Unit13>
<Filename Value="..\..\xlsxooxml.pas"/> <Filename Value="..\..\xlsxooxml.pas"/>
<UnitName Value="xlsxooxml"/> <UnitName Value="xlsxooxml"/>
<CursorPos X="1" Y="89"/> <CursorPos X="1" Y="248"/>
<TopLine Value="79"/> <TopLine Value="244"/>
<EditorIndex Value="2"/> <EditorIndex Value="2"/>
<UsageCount Value="13"/> <UsageCount Value="13"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -150,123 +150,123 @@
<JumpHistory Count="30" HistoryIndex="29"> <JumpHistory Count="30" HistoryIndex="29">
<Position1> <Position1>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="77" Column="7" TopLine="76"/> <Caret Line="567" Column="5" TopLine="548"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="137" Column="40" TopLine="129"/> <Caret Line="622" Column="1" TopLine="618"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpolestorage.pas"/>
<Caret Line="563" Column="5" TopLine="544"/> <Caret Line="621" Column="29" TopLine="611"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="486" Column="5" TopLine="467"/> <Caret Line="428" Column="5" TopLine="403"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="510" Column="5" TopLine="491"/> <Caret Line="458" Column="15" TopLine="434"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="94" Column="46" TopLine="84"/> <Caret Line="386" Column="1" TopLine="372"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="686" Column="5" TopLine="667"/> <Caret Line="390" Column="26" TopLine="377"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="567" Column="5" TopLine="548"/> <Caret Line="420" Column="32" TopLine="407"/>
</Position8> </Position8>
<Position9> <Position9>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="622" Column="1" TopLine="618"/> <Caret Line="421" Column="14" TopLine="408"/>
</Position9> </Position9>
<Position10> <Position10>
<Filename Value="..\..\fpolestorage.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="621" Column="29" TopLine="611"/> <Caret Line="460" Column="33" TopLine="440"/>
</Position10> </Position10>
<Position11> <Position11>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="428" Column="5" TopLine="403"/> <Caret Line="181" Column="91" TopLine="160"/>
</Position11> </Position11>
<Position12> <Position12>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="458" Column="15" TopLine="434"/> <Caret Line="769" Column="83" TopLine="754"/>
</Position12> </Position12>
<Position13> <Position13>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="386" Column="1" TopLine="372"/> <Caret Line="102" Column="15" TopLine="89"/>
</Position13> </Position13>
<Position14> <Position14>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="390" Column="26" TopLine="377"/> <Caret Line="103" Column="15" TopLine="90"/>
</Position14> </Position14>
<Position15> <Position15>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="420" Column="32" TopLine="407"/> <Caret Line="404" Column="5" TopLine="379"/>
</Position15> </Position15>
<Position16> <Position16>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="421" Column="14" TopLine="408"/> <Caret Line="187" Column="1" TopLine="172"/>
</Position16> </Position16>
<Position17> <Position17>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="460" Column="33" TopLine="440"/> <Caret Line="380" Column="17" TopLine="362"/>
</Position17> </Position17>
<Position18> <Position18>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="181" Column="91" TopLine="160"/> <Caret Line="412" Column="1" TopLine="404"/>
</Position18> </Position18>
<Position19> <Position19>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="769" Column="83" TopLine="754"/> <Caret Line="716" Column="1" TopLine="702"/>
</Position19> </Position19>
<Position20> <Position20>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="102" Column="15" TopLine="89"/> <Caret Line="167" Column="17" TopLine="154"/>
</Position20> </Position20>
<Position21> <Position21>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="103" Column="15" TopLine="90"/>
</Position21>
<Position22>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="404" Column="5" TopLine="379"/>
</Position22>
<Position23>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="187" Column="1" TopLine="172"/>
</Position23>
<Position24>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="380" Column="17" TopLine="362"/>
</Position24>
<Position25>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="412" Column="1" TopLine="404"/>
</Position25>
<Position26>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="716" Column="1" TopLine="702"/>
</Position26>
<Position27>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="167" Column="17" TopLine="154"/>
</Position27>
<Position28>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="69" Column="1" TopLine="57"/> <Caret Line="69" Column="1" TopLine="57"/>
</Position28> </Position21>
<Position29> <Position22>
<Filename Value="ooxmlwrite.lpr"/> <Filename Value="ooxmlwrite.lpr"/>
<Caret Line="68" Column="57" TopLine="46"/> <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> </Position29>
<Position30> <Position30>
<Filename Value="..\..\xlsxooxml.pas"/> <Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="102" Column="1" TopLine="77"/> <Caret Line="211" Column="20" TopLine="188"/>
</Position30> </Position30>
</JumpHistory> </JumpHistory>
</ProjectOptions> </ProjectOptions>

View File

@ -43,18 +43,6 @@ begin
end; end;
} }
// Write the formula E1 = A1 + B1
// or, in RPN: A1, B1, +
SetLength(MyFormula, 3);
MyFormula[0].TokenID := INT_EXCEL_TOKEN_TREFV; {A1}
MyFormula[0].Col := 0;
MyFormula[0].Row := 0;
MyFormula[1].TokenID := INT_EXCEL_TOKEN_TREFV; {B1}
MyFormula[1].Col := 1;
MyFormula[1].Row := 0;
MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; {+}
MyWorksheet.WriteRPNFormula(0, 4, MyFormula);
// Creates a new worksheet // Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2'); MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
@ -65,7 +53,7 @@ begin
MyWorksheet.WriteUTF8Text(0, 3, 'Fourth'); MyWorksheet.WriteUTF8Text(0, 3, 'Fourth');
// Save the spreadsheet to a file // Save the spreadsheet to a file
MyWorkbook.WriteToFile(MyDir + 'test' + STR_OOXML_EXCEL_EXTENSION, sfOOXML); MyWorkbook.WriteToFile(MyDir + 'test.xlsx', sfOOXML);
MyWorkbook.Free; MyWorkbook.Free;
end. end.

View File

@ -11,7 +11,7 @@
<TargetFileExt Value=".exe"/> <TargetFileExt Value=".exe"/>
<Title Value="opendocwrite"/> <Title Value="opendocwrite"/>
<UseAppBundle Value="False"/> <UseAppBundle Value="False"/>
<ActiveEditorIndexAtStart Value="0"/> <ActiveEditorIndexAtStart Value="4"/>
</General> </General>
<VersionInfo> <VersionInfo>
<ProjectVersion Value=""/> <ProjectVersion Value=""/>
@ -33,13 +33,13 @@
<PackageName Value="laz_fpspreadsheet"/> <PackageName Value="laz_fpspreadsheet"/>
</Item1> </Item1>
</RequiredPackages> </RequiredPackages>
<Units Count="16"> <Units Count="20">
<Unit0> <Unit0>
<Filename Value="opendocwrite.lpr"/> <Filename Value="opendocwrite.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
<UnitName Value="opendocwrite"/> <UnitName Value="opendocwrite"/>
<CursorPos X="1" Y="70"/> <CursorPos X="1" Y="34"/>
<TopLine Value="45"/> <TopLine Value="20"/>
<EditorIndex Value="0"/> <EditorIndex Value="0"/>
<UsageCount Value="309"/> <UsageCount Value="309"/>
<Loaded Value="True"/> <Loaded Value="True"/>
@ -116,10 +116,10 @@
<Unit10> <Unit10>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/> <UnitName Value="fpspreadsheet"/>
<CursorPos X="1" Y="366"/> <CursorPos X="1" Y="794"/>
<TopLine Value="349"/> <TopLine Value="792"/>
<EditorIndex Value="5"/> <EditorIndex Value="4"/>
<UsageCount Value="98"/> <UsageCount Value="100"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit10> </Unit10>
<Unit11> <Unit11>
@ -131,28 +131,26 @@
<Unit12> <Unit12>
<Filename Value="..\..\fpsopendocument.pas"/> <Filename Value="..\..\fpsopendocument.pas"/>
<UnitName Value="fpsopendocument"/> <UnitName Value="fpsopendocument"/>
<CursorPos X="1" Y="118"/> <CursorPos X="1" Y="384"/>
<TopLine Value="107"/> <TopLine Value="373"/>
<EditorIndex Value="2"/> <EditorIndex Value="2"/>
<UsageCount Value="16"/> <UsageCount Value="21"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit12> </Unit12>
<Unit13> <Unit13>
<Filename Value="..\..\xlsxooxml.pas"/> <Filename Value="..\..\xlsxooxml.pas"/>
<UnitName Value="xlsxooxml"/> <UnitName Value="xlsxooxml"/>
<CursorPos X="1" Y="268"/> <CursorPos X="1" Y="35"/>
<TopLine Value="253"/> <TopLine Value="16"/>
<EditorIndex Value="4"/> <EditorIndex Value="3"/>
<UsageCount Value="16"/> <UsageCount Value="21"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit13> </Unit13>
<Unit14> <Unit14>
<Filename Value="..\..\..\..\..\..\..\..\usr\local\share\fpcsrc\rtl\objpas\sysutils\sysstrh.inc"/> <Filename Value="..\..\..\..\..\..\..\..\usr\local\share\fpcsrc\rtl\objpas\sysutils\sysstrh.inc"/>
<CursorPos X="10" Y="154"/> <CursorPos X="38" Y="145"/>
<TopLine Value="141"/> <TopLine Value="141"/>
<EditorIndex Value="3"/> <UsageCount Value="15"/>
<UsageCount Value="13"/>
<Loaded Value="True"/>
</Unit14> </Unit14>
<Unit15> <Unit15>
<Filename Value="..\..\fpsallformats.pas"/> <Filename Value="..\..\fpsallformats.pas"/>
@ -160,127 +158,159 @@
<CursorPos X="44" Y="13"/> <CursorPos X="44" Y="13"/>
<TopLine Value="1"/> <TopLine Value="1"/>
<EditorIndex Value="1"/> <EditorIndex Value="1"/>
<UsageCount Value="11"/> <UsageCount Value="16"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit15> </Unit15>
<Unit16>
<Filename Value="..\..\..\..\..\..\..\..\usr\local\share\fpcsrc\packages\paszlib\src\zipper.pp"/>
<UnitName Value="zipper"/>
<CursorPos X="24" Y="7"/>
<TopLine Value="1"/>
<UsageCount Value="12"/>
</Unit16>
<Unit17>
<Filename Value="..\..\..\..\..\..\..\..\usr\local\share\fpcsrc\rtl\objpas\sysutils\finah.inc"/>
<CursorPos X="27" Y="25"/>
<TopLine Value="17"/>
<UsageCount Value="10"/>
</Unit17>
<Unit18>
<Filename Value="..\..\..\..\..\..\..\..\usr\local\share\fpcsrc\rtl\objpas\sysutils\fina.inc"/>
<CursorPos X="28" Y="258"/>
<TopLine Value="249"/>
<UsageCount Value="10"/>
</Unit18>
<Unit19>
<Filename Value="..\..\fpszipper.pp"/>
<UnitName Value="fpszipper"/>
<CursorPos X="36" Y="9"/>
<TopLine Value="1"/>
<EditorIndex Value="5"/>
<UsageCount Value="13"/>
<Loaded Value="True"/>
</Unit19>
</Units> </Units>
<JumpHistory Count="29" HistoryIndex="28"> <JumpHistory Count="30" HistoryIndex="29">
<Position1> <Position1>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="754" Column="1" TopLine="741"/> <Caret Line="153" Column="72" TopLine="137"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="755" Column="1" TopLine="742"/> <Caret Line="159" Column="13" TopLine="137"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="757" Column="1" TopLine="744"/> <Caret Line="187" Column="32" TopLine="174"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="759" Column="1" TopLine="746"/> <Caret Line="190" Column="13" TopLine="174"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="..\..\fpsopendocument.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="392" Column="1" TopLine="379"/> <Caret Line="193" Column="34" TopLine="174"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="87" Column="1" TopLine="79"/> <Caret Line="226" Column="33" TopLine="213"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="211" Column="34" TopLine="196"/> <Caret Line="97" Column="16" TopLine="85"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="22" Column="40" TopLine="8"/>
</Position8>
<Position9>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="48" Column="22" TopLine="35"/>
</Position9>
<Position10>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="194" Column="7" TopLine="181"/>
</Position10>
<Position11>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="329" Column="51" TopLine="316"/>
</Position11>
<Position12>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="257" Column="34" TopLine="242"/>
</Position12>
<Position13>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="286" Column="34" TopLine="271"/>
</Position13>
<Position14>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="350" Column="38" TopLine="336"/>
</Position14>
<Position15>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="207" Column="1" TopLine="196"/>
</Position15>
<Position16>
<Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="556" Column="34" TopLine="542"/>
</Position16>
<Position17>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="50" Column="19" TopLine="37"/>
</Position17>
<Position18>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="150" Column="34" TopLine="137"/>
</Position18>
<Position19>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="153" Column="72" TopLine="137"/>
</Position19>
<Position20>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="159" Column="13" TopLine="137"/>
</Position20>
<Position21>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="187" Column="32" TopLine="174"/>
</Position21>
<Position22>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="190" Column="13" TopLine="174"/>
</Position22>
<Position23>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="193" Column="34" TopLine="174"/>
</Position23>
<Position24>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="226" Column="33" TopLine="213"/>
</Position24>
<Position25>
<Filename Value="..\..\xlsbiff2.pas"/>
<Caret Line="97" Column="16" TopLine="85"/>
</Position25>
<Position26>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="601" Column="25" TopLine="588"/> <Caret Line="601" Column="25" TopLine="588"/>
</Position26> </Position8>
<Position27> <Position9>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="673" Column="34" TopLine="659"/> <Caret Line="673" Column="34" TopLine="659"/>
</Position27> </Position9>
<Position28> <Position10>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="700" Column="34" TopLine="686"/> <Caret Line="700" Column="34" TopLine="686"/>
</Position28> </Position10>
<Position29> <Position11>
<Filename Value="opendocwrite.lpr"/> <Filename Value="opendocwrite.lpr"/>
<Caret Line="13" Column="45" TopLine="5"/> <Caret Line="13" Column="45" TopLine="5"/>
</Position11>
<Position12>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="40" Column="17" TopLine="28"/>
</Position12>
<Position13>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="350" Column="29" TopLine="339"/>
</Position13>
<Position14>
<Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="51" Column="25" TopLine="39"/>
</Position14>
<Position15>
<Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="103" Column="31" TopLine="103"/>
</Position15>
<Position16>
<Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="51" Column="15" TopLine="50"/>
</Position16>
<Position17>
<Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="249" Column="5" TopLine="224"/>
</Position17>
<Position18>
<Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="242" Column="1" TopLine="238"/>
</Position18>
<Position19>
<Filename Value="opendocwrite.lpr"/>
<Caret Line="30" Column="5" TopLine="10"/>
</Position19>
<Position20>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="51" Column="22" TopLine="39"/>
</Position20>
<Position21>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="68" Column="10" TopLine="55"/>
</Position21>
<Position22>
<Filename Value="..\..\xlsxooxml.pas"/>
<Caret Line="268" Column="5" TopLine="244"/>
</Position22>
<Position23>
<Filename Value="..\..\fpsopendocument.pas"/>
<Caret Line="38" Column="36" TopLine="32"/>
</Position23>
<Position24>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="62" Column="4" TopLine="52"/>
</Position24>
<Position25>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="66" Column="21" TopLine="53"/>
</Position25>
<Position26>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="102" Column="20" TopLine="89"/>
</Position26>
<Position27>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="105" Column="20" TopLine="94"/>
</Position27>
<Position28>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="764" Column="1" TopLine="739"/>
</Position28>
<Position29>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="777" Column="36" TopLine="767"/>
</Position29> </Position29>
<Position30>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="785" Column="10" TopLine="762"/>
</Position30>
</JumpHistory> </JumpHistory>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -10,17 +10,14 @@ program opendocwrite;
{$mode delphi}{$H+} {$mode delphi}{$H+}
uses uses
Classes, SysUtils, fpspreadsheet, fpsallformats, laz_fpspreadsheet; Classes, SysUtils, fpspreadsheet, fpsallformats,
laz_fpspreadsheet;
var var
MyWorkbook: TsWorkbook; MyWorkbook: TsWorkbook;
MyWorksheet: TsWorksheet; MyWorksheet: TsWorksheet;
MyFormula: TRPNFormula;
MyDir: string; MyDir: string;
i: Integer;
a: TStringList;
begin begin
// Open the output file
MyDir := ExtractFilePath(ParamStr(0)); MyDir := ExtractFilePath(ParamStr(0));
// Create the spreadsheet // Create the spreadsheet
@ -33,38 +30,16 @@ begin
MyWorksheet.WriteNumber(0, 2, 3.0); MyWorksheet.WriteNumber(0, 2, 3.0);
MyWorksheet.WriteNumber(0, 3, 4.0); MyWorksheet.WriteNumber(0, 3, 4.0);
{ Uncommend this to test large XLS files
for i := 2 to 20 do
begin
MyWorksheet.WriteAnsiText(i, 0, ParamStr(0));
MyWorksheet.WriteAnsiText(i, 1, ParamStr(0));
MyWorksheet.WriteAnsiText(i, 2, ParamStr(0));
MyWorksheet.WriteAnsiText(i, 3, ParamStr(0));
end;
}
// Write the formula E1 = A1 + B1
// or, in RPN: A1, B1, +
(* SetLength(MyFormula, 3);
MyFormula[0].TokenID := INT_EXCEL_TOKEN_TREFV; {A1}
MyFormula[0].Col := 0;
MyFormula[0].Row := 0;
MyFormula[1].TokenID := INT_EXCEL_TOKEN_TREFV; {B1}
MyFormula[1].Col := 1;
MyFormula[1].Row := 0;
MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; {+}
MyWorksheet.WriteRPNFormula(0, 4, MyFormula);
// Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
*)
// Write some string cells // Write some string cells
MyWorksheet.WriteUTF8Text(4, 2, 'Total:'); MyWorksheet.WriteUTF8Text(4, 2, 'Total:');
MyWorksheet.WriteNumber(4, 3, 10.0); MyWorksheet.WriteNumber(4, 3, 10.0);
// Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2');
// Save the spreadsheet to a file // Save the spreadsheet to a file
MyWorkbook.WriteToFile(MyDir + 'test', sfOpenDocument); MyWorkbook.WriteToFile(MyDir + 'test.ods',
sfOpenDocument);
MyWorkbook.Free; MyWorkbook.Free;
end. end.

View File

@ -10,8 +10,7 @@ meta.xml - Authoring data
settings.xml - User persistent viewing information, such as zoom, cursor position, etc. settings.xml - User persistent viewing information, such as zoom, cursor position, etc.
styles.xml - Styles, which are the only way to do formatting styles.xml - Styles, which are the only way to do formatting
mimetype - application/vnd.oasis.opendocument.spreadsheet mimetype - application/vnd.oasis.opendocument.spreadsheet
META-INF META-INF\manifest.xml - Describes the other files in the archive
manifest.xml -
Specifications obtained from: Specifications obtained from:
@ -28,7 +27,8 @@ unit fpsopendocument;
interface interface
uses uses
Classes, SysUtils, zipper, Classes, SysUtils,
fpszipper, {NOTE: fpszipper is the latest zipper.pp Change to standard zipper when FPC 2.4 is released }
fpspreadsheet; fpspreadsheet;
type type
@ -37,25 +37,23 @@ type
TsSpreadOpenDocWriter = class(TsCustomSpreadWriter) TsSpreadOpenDocWriter = class(TsCustomSpreadWriter)
protected protected
FZip: TZipper;
// Strings with the contents of files // Strings with the contents of files
// filename\ FMeta, FSettings, FStyles, FContent, FMimetype: string;
FMeta, FSettings, FStyles: string;
FContent: string;
FMimetype: string;
// filename\META-INF
FMetaInfManifest: string; FMetaInfManifest: string;
// Streams with the contents of files
FSMeta, FSSettings, FSStyles, FSContent, FSMimetype: TStringStream;
FSMetaInfManifest: TStringStream;
// Routines to write those files // Routines to write those files
procedure WriteGlobalFiles; procedure WriteGlobalFiles;
procedure WriteContent(AData: TsWorkbook); procedure WriteContent(AData: TsWorkbook);
procedure WriteWorksheet(CurSheet: TsWorksheet); procedure WriteWorksheet(CurSheet: TsWorksheet);
public public
{ General writing methods } { General writing methods }
procedure WriteStringToFile(AFileName, AString: string); procedure WriteStringToFile(AString, AFileName: string);
procedure WriteToFile(AFileName: string; AData: TsWorkbook); override; procedure WriteToFile(AFileName: string; AData: TsWorkbook); override;
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override; procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override;
{ Record writing methods } { Record writing methods }
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override; procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override; procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
end; end;
@ -67,11 +65,11 @@ const
XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>'; XML_HEADER = '<?xml version="1.0" encoding="utf-8" ?>';
{ OpenDocument Directory structure constants } { OpenDocument Directory structure constants }
OOXML_PATH_CONTENT = 'content.xml'; OPENDOC_PATH_CONTENT = 'content.xml';
OOXML_PATH_META = 'meta.xml'; OPENDOC_PATH_META = 'meta.xml';
OOXML_PATH_SETTINGS = 'settings.xml'; OPENDOC_PATH_SETTINGS = 'settings.xml';
OOXML_PATH_STYLES = 'styles.xml'; OPENDOC_PATH_STYLES = 'styles.xml';
OOXML_PATH_MIMETYPE = 'mimetype'; OPENDOC_PATH_MIMETYPE = 'mimetype';
OPENDOC_PATH_METAINF = 'META-INF' + PathDelim; OPENDOC_PATH_METAINF = 'META-INF' + PathDelim;
OPENDOC_PATH_METAINF_MANIFEST = 'META-INF' + PathDelim + 'manifest.xml'; OPENDOC_PATH_METAINF_MANIFEST = 'META-INF' + PathDelim + 'manifest.xml';
@ -246,6 +244,7 @@ begin
' <office:body>' + LineEnding + ' <office:body>' + LineEnding +
' <office:spreadsheet>' + LineEnding; ' <office:spreadsheet>' + LineEnding;
// Write all worksheets
for i := 0 to AData.GetWorksheetCount - 1 do for i := 0 to AData.GetWorksheetCount - 1 do
begin begin
WriteWorksheet(Adata.GetWorksheetByIndex(i)); WriteWorksheet(Adata.GetWorksheetByIndex(i));
@ -312,13 +311,10 @@ begin
' </table:table>' + LineEnding; ' </table:table>' + LineEnding;
end; end;
{******************************************************************* {
* TsSpreadOOXMLWriter.WriteStringToFile () Writes a string to a file. Helper convenience method.
* }
* DESCRIPTION: Writes a string to a file. Helper convenience method. procedure TsSpreadOpenDocWriter.WriteStringToFile(AString, AFileName: string);
*
*******************************************************************}
procedure TsSpreadOpenDocWriter.WriteStringToFile(AFileName, AString: string);
var var
TheStream : TFileStream; TheStream : TFileStream;
S : String; S : String;
@ -329,57 +325,70 @@ begin
TheStream.Free; TheStream.Free;
end; end;
{******************************************************************* {
* TsSpreadOOXMLWriter.WriteToFile () Writes an OOXML document to the disc.
* }
* DESCRIPTION: Writes an OOXML document to the disc
*
*******************************************************************}
procedure TsSpreadOpenDocWriter.WriteToFile(AFileName: string; AData: TsWorkbook); procedure TsSpreadOpenDocWriter.WriteToFile(AFileName: string; AData: TsWorkbook);
var var
TempDir: string; FZip: TZipper;
begin begin
{FZip := TZipper.Create; { Fill the strings with the contents of the files }
FZip.ZipFiles(AFileName, x);
FZip.Free;}
// WriteToStream(nil, AData);
WriteGlobalFiles(); WriteGlobalFiles();
WriteContent(AData); WriteContent(AData);
TempDir := IncludeTrailingBackslash(AFileName); { Write the data to streams }
{ files on the root path } FSMeta := TStringStream.Create(FMeta);
FSSettings := TStringStream.Create(FSettings);
FSStyles := TStringStream.Create(FStyles);
FSContent := TStringStream.Create(FContent);
FSMimetype := TStringStream.Create(FMimetype);
FSMetaInfManifest := TStringStream.Create(FMetaInfManifest);
ForceDirectories(TempDir); { Now compress the files }
WriteStringToFile(TempDir + OOXML_PATH_CONTENT, FContent); FZip := TZipper.Create;
try
WriteStringToFile(TempDir + OOXML_PATH_META, FMeta); FZip.FileName := AFileName;
WriteStringToFile(TempDir + OOXML_PATH_SETTINGS, FSettings); FZip.Entries.AddFileEntry(FSMeta, OPENDOC_PATH_META);
FZip.Entries.AddFileEntry(FSSettings, OPENDOC_PATH_SETTINGS);
FZip.Entries.AddFileEntry(FSStyles, OPENDOC_PATH_STYLES);
FZip.Entries.AddFileEntry(FSContent, OPENDOC_PATH_CONTENT);
FZip.Entries.AddFileEntry(FSMimetype, OPENDOC_PATH_MIMETYPE);
FZip.Entries.AddFileEntry(FSMetaInfManifest, OPENDOC_PATH_METAINF_MANIFEST);
WriteStringToFile(TempDir + OOXML_PATH_STYLES, FStyles); FZip.ZipAllFiles;
finally
WriteStringToFile(TempDir + OOXML_PATH_MIMETYPE, FMimetype); FZip.Free;
FSMeta.Free;
{ META-INF directory } FSSettings.Free;
FSStyles.Free;
ForceDirectories(TempDir + OPENDOC_PATH_METAINF); FSContent.Free;
FSMimetype.Free;
WriteStringToFile(TempDir + OPENDOC_PATH_METAINF_MANIFEST, FMetaInfManifest); FSMetaInfManifest.Free;
end;
end; end;
procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream; AData: TsWorkbook); procedure TsSpreadOpenDocWriter.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin begin
// Not supported at the moment
raise Exception.Create('TsSpreadOpenDocWriter.WriteToStream not supported');
end; end;
procedure TsSpreadOpenDocWriter.WriteFormula(AStream: TStream; const ARow, procedure TsSpreadOpenDocWriter.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula); ACol: Word; const AFormula: TsFormula);
begin begin
{ // The row should already be the correct one
FContent := FContent +
' <table:table-cell office:value-type="string">' + LineEnding +
' <text:p>' + AFormula.DoubleValue + '</text:p>' + LineEnding +
' </table:table-cell>' + LineEnding;
<table:table-cell table:formula="of:=[.A1]+[.B2]" office:value-type="float" office:value="1833">
<text:p>1833</text:p>
</table:table-cell>}
end; end;
procedure TsSpreadOpenDocWriter.WriteLabel(AStream: TStream; const ARow, procedure TsSpreadOpenDocWriter.WriteLabel(AStream: TStream; const ARow,
@ -402,12 +411,9 @@ begin
' </table:table-cell>' + LineEnding; ' </table:table-cell>' + LineEnding;
end; end;
{******************************************************************* {
* Initialization section Registers this reader / writer on fpSpreadsheet
* }
* Registers this reader / writer on fpSpreadsheet
*
*******************************************************************}
initialization initialization
RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadOpenDocWriter, sfOpenDocument); RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadOpenDocWriter, sfOpenDocument);

View File

@ -26,38 +26,35 @@ const
STR_OOXML_EXCEL_EXTENSION = '.xlsx'; STR_OOXML_EXCEL_EXTENSION = '.xlsx';
STR_OPENDOCUMENT_CALC_EXTENSION = '.ods'; STR_OPENDOCUMENT_CALC_EXTENSION = '.ods';
const
{ TokenID values }
{ Binary Operator Tokens }
INT_EXCEL_TOKEN_TADD = $03;
INT_EXCEL_TOKEN_TSUB = $04;
INT_EXCEL_TOKEN_TMUL = $05;
INT_EXCEL_TOKEN_TDIV = $06;
INT_EXCEL_TOKEN_TPOWER = $07;
{ Constant Operand Tokens }
INT_EXCEL_TOKEN_TNUM = $1F;
{ Operand Tokens }
INT_EXCEL_TOKEN_TREFR = $24;
INT_EXCEL_TOKEN_TREFV = $44;
INT_EXCEL_TOKEN_TREFA = $64;
type type
{@@ A Token of a RPN Token array for formulas } {@@ Describes a formula
TRPNToken = record Supported syntax:
TokenID: Byte;
Col: Byte; =A1+B1+C1/D2... - Array with simple mathematical operations
Row: Word;
=SUM(A1:D1) - SUM operation in a interval
}
TsFormula = record
FormulaStr: string;
DoubleValue: double; DoubleValue: double;
end; end;
{@@ RPN Token array for formulas } {@@ Expanded formula. Used by backend modules. Provides more information then the text only }
TRPNFormula = array of TRPNToken; TFEKind = (fekCell, fekAdd, fekSub, fekDiv, fekMul,
fekOpSUM);
TsFormulaElement = record
ElementKind: TFEKind;
Row1, Row2: Word;
Col1, Col2: Byte;
DoubleValue: double;
end;
TsExpandedFormula = array of TsFormulaElement;
{@@ Describes the type of content of a cell on a TsWorksheet } {@@ Describes the type of content of a cell on a TsWorksheet }
@ -69,7 +66,7 @@ type
Col: Byte; Col: Byte;
Row: Word; Row: Word;
ContentType: TCellContentType; ContentType: TCellContentType;
FormulaValue: TRPNFormula; FormulaValue: TsFormula;
NumberValue: double; NumberValue: double;
UTF8StringValue: ansistring; UTF8StringValue: ansistring;
end; end;
@ -81,8 +78,6 @@ type
TsCustomSpreadReader = class; TsCustomSpreadReader = class;
TsCustomSpreadWriter = class; TsCustomSpreadWriter = class;
{@@ TsWorksheet }
{ TsWorksheet } { TsWorksheet }
TsWorksheet = class TsWorksheet = class
@ -105,11 +100,9 @@ type
procedure RemoveAllCells; procedure RemoveAllCells;
procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring); procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring);
procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double); procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double);
procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TRPNFormula); procedure WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula);
end; end;
{@@ TsWorkbook }
{ TsWorkbook } { TsWorkbook }
TsWorkbook = class TsWorkbook = class
@ -140,8 +133,6 @@ type
TsSpreadReaderClass = class of TsCustomSpreadReader; TsSpreadReaderClass = class of TsCustomSpreadReader;
{@@ TsCustomSpreadReader }
{ TsCustomSpreadReader } { TsCustomSpreadReader }
TsCustomSpreadReader = class TsCustomSpreadReader = class
@ -162,19 +153,19 @@ type
TsSpreadWriterClass = class of TsCustomSpreadWriter; TsSpreadWriterClass = class of TsCustomSpreadWriter;
{@@ TsCustomSpreadWriter }
{ TsCustomSpreadWriter } { TsCustomSpreadWriter }
TsCustomSpreadWriter = class TsCustomSpreadWriter = class
public public
{ Helper routines }
function ExpandFormula(AFormula: TsFormula): TsExpandedFormula;
{ General writing methods } { General writing methods }
procedure WriteCellCallback(data, arg: pointer); procedure WriteCellCallback(data, arg: pointer);
procedure WriteCellsToStream(AStream: TStream; ACells: TFPList); procedure WriteCellsToStream(AStream: TStream; ACells: TFPList);
procedure WriteToFile(AFileName: string; AData: TsWorkbook); virtual; procedure WriteToFile(AFileName: string; AData: TsWorkbook); virtual;
procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual; procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual;
{ Record writing methods } { Record writing methods }
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); virtual; abstract; procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); virtual; abstract;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); virtual; abstract; procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); virtual; abstract;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); virtual; abstract; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); virtual; abstract;
end; end;
@ -494,9 +485,9 @@ end;
@param ARow The row of the cell @param ARow The row of the cell
@param ACol The column of the cell @param ACol The column of the cell
@param AFormula The formula in RPN array format @param AFormula The formula to be written
} }
procedure TsWorksheet.WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TRPNFormula); procedure TsWorksheet.WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula);
var var
ACell: PCell; ACell: PCell;
begin begin
@ -758,6 +749,50 @@ end;
{ TsCustomSpreadWriter } { TsCustomSpreadWriter }
{@@
Expands a formula, separating it in it's constituent parts,
so that it is already partially parsed and it is easier to
convert it into the format supported by the writer module
}
function TsCustomSpreadWriter.ExpandFormula(AFormula: TsFormula): TsExpandedFormula;
var
StrPos: Integer;
ResPos: Integer;
begin
ResPos := -1;
SetLength(Result, 0);
// The formula needs to start with a =
if AFormula.FormulaStr[1] <> '=' then raise Exception.Create('Formula doesn''t start with =');
StrPos := 2;
while Length(AFormula.FormulaStr) <= StrPos do
begin
// Checks for cell with the format [Letter][Number]
{ if (AFormula.FormulaStr[StrPos] in [a..zA..Z]) and
(AFormula.FormulaStr[StrPos + 1] in [0..9]) then
begin
Inc(ResPos);
SetLength(Result, ResPos + 1);
Result[ResPos].ElementKind := fekCell;
// Result[ResPos].Col1 := fekCell;
Result[ResPos].Row1 := AFormula.FormulaStr[StrPos + 1];
Inc(StrPos);
end
// Checks for arithmetical operations
else} if AFormula.FormulaStr[StrPos] = '+' then
begin
Inc(ResPos);
SetLength(Result, ResPos + 1);
Result[ResPos].ElementKind := fekAdd;
end;
Inc(StrPos);
end;
end;
{@@ {@@
Helper function for the spreadsheet writers. Helper function for the spreadsheet writers.

File diff suppressed because it is too large Load Diff

View File

@ -8,13 +8,13 @@
<PathDelim Value="\"/> <PathDelim Value="\"/>
<SearchPaths> <SearchPaths>
<OtherUnitFiles Value="C:\Programas\lazarus-ccr\components\fpspreadsheet\"/> <OtherUnitFiles Value="C:\Programas\lazarus-ccr\components\fpspreadsheet\"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)\"/> <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths> </SearchPaths>
<Other> <Other>
<CompilerPath Value="$(CompPath)"/> <CompilerPath Value="$(CompPath)"/>
</Other> </Other>
</CompilerOptions> </CompilerOptions>
<Files Count="9"> <Files Count="10">
<Item1> <Item1>
<Filename Value="fpolestorage.pas"/> <Filename Value="fpolestorage.pas"/>
<UnitName Value="fpolestorage"/> <UnitName Value="fpolestorage"/>
@ -51,6 +51,10 @@
<Filename Value="fpsutils.pas"/> <Filename Value="fpsutils.pas"/>
<UnitName Value="fpsutils"/> <UnitName Value="fpsutils"/>
</Item9> </Item9>
<Item10>
<Filename Value="fpszipper.pp"/>
<UnitName Value="fpszipper"/>
</Item10>
</Files> </Files>
<Type Value="RunAndDesignTime"/> <Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="1"> <RequiredPkgs Count="1">

View File

@ -8,7 +8,7 @@ interface
uses uses
fpolestorage, fpsallformats, fpsopendocument, fpspreadsheet, xlsbiff2, fpolestorage, fpsallformats, fpsopendocument, fpspreadsheet, xlsbiff2,
xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, LazarusPackageIntf; xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, fpszipper, LazarusPackageIntf;
implementation implementation

View File

@ -59,7 +59,7 @@ type
{ Record writing methods } { Record writing methods }
procedure WriteBOF(AStream: TStream); procedure WriteBOF(AStream: TStream);
procedure WriteEOF(AStream: TStream); procedure WriteEOF(AStream: TStream);
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override; procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override; procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
end; end;
@ -84,17 +84,43 @@ const
INT_EXCEL_CHART = $0020; INT_EXCEL_CHART = $0020;
INT_EXCEL_MACRO_SHEET = $0040; INT_EXCEL_MACRO_SHEET = $0040;
{ Types and constants for formulas }
type
TRPNItem = record
TokenID: Byte;
Col: Byte;
Row: Word;
DoubleValue: Double;
end;
TRPNFormula = array of TRPNItem;
const
{ TokenID values }
{ Binary Operator Tokens }
INT_EXCEL_TOKEN_TADD = $03;
INT_EXCEL_TOKEN_TSUB = $04;
INT_EXCEL_TOKEN_TMUL = $05;
INT_EXCEL_TOKEN_TDIV = $06;
INT_EXCEL_TOKEN_TPOWER = $07;
{ Constant Operand Tokens }
INT_EXCEL_TOKEN_TNUM = $1F;
{ Operand Tokens }
INT_EXCEL_TOKEN_TREFR = $24;
INT_EXCEL_TOKEN_TREFV = $44;
INT_EXCEL_TOKEN_TREFA = $64;
{ TsSpreadBIFF2Writer } { TsSpreadBIFF2Writer }
{******************************************************************* {
* TsSpreadBIFF2Writer.WriteToStream () Writes an Excel 2 file to a stream
*
* DESCRIPTION: Writes an Excel 2 file to a stream Excel 2.x files support only one Worksheet per Workbook,
* so only the first will be written.
* Excel 2.x files support only one Worksheet per Workbook, }
* so only the first will be written.
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteToStream(AStream: TStream; AData: TsWorkbook); procedure TsSpreadBIFF2Writer.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin begin
WriteBOF(AStream); WriteBOF(AStream);
@ -104,14 +130,11 @@ begin
WriteEOF(AStream); WriteEOF(AStream);
end; end;
{******************************************************************* {
* TsSpreadBIFF2Writer.WriteBOF () Writes an Excel 2 BOF record
*
* DESCRIPTION: Writes an Excel 2 BOF record This must be the first record on an Excel 2 stream
* }
* This must be the first record on an Excel 2 stream
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteBOF(AStream: TStream); procedure TsSpreadBIFF2Writer.WriteBOF(AStream: TStream);
begin begin
{ BIFF Record header } { BIFF Record header }
@ -125,14 +148,11 @@ begin
AStream.WriteWord(WordToLE(INT_EXCEL_SHEET)); AStream.WriteWord(WordToLE(INT_EXCEL_SHEET));
end; end;
{******************************************************************* {
* TsSpreadBIFF2Writer.WriteEOF () Writes an Excel 2 EOF record
*
* DESCRIPTION: Writes an Excel 2 EOF record This must be the last record on an Excel 2 stream
* }
* This must be the last record on an Excel 2 stream
*
*******************************************************************}
procedure TsSpreadBIFF2Writer.WriteEOF(AStream: TStream); procedure TsSpreadBIFF2Writer.WriteEOF(AStream: TStream);
begin begin
{ BIFF Record header } { BIFF Record header }
@ -140,25 +160,31 @@ begin
AStream.WriteWord($0000); AStream.WriteWord($0000);
end; end;
{******************************************************************* {
* TsSpreadBIFF2Writer.WriteFormula () Writes an Excel 2 FORMULA record
*
* DESCRIPTION: Writes an Excel 2 FORMULA record The formula needs to be converted from usual user-readable string
* to an RPN array
* To input a formula to this method, first convert it
* to RPN, and then list all it's members in the // or, in RPN: A1, B1, +
* AFormula array SetLength(MyFormula, 3);
* MyFormula[0].TokenID := INT_EXCEL_TOKEN_TREFV; A1
*******************************************************************} MyFormula[0].Col := 0;
MyFormula[0].Row := 0;
MyFormula[1].TokenID := INT_EXCEL_TOKEN_TREFV; B1
MyFormula[1].Col := 1;
MyFormula[1].Row := 0;
MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; +
}
procedure TsSpreadBIFF2Writer.WriteFormula(AStream: TStream; const ARow, procedure TsSpreadBIFF2Writer.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula); ACol: Word; const AFormula: TsFormula);
var {var
FormulaResult: double; FormulaResult: double;
i: Integer; i: Integer;
RPNLength: Word; RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Cardinal; TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;}
begin begin
RPNLength := 0; (* RPNLength := 0;
FormulaResult := 0.0; FormulaResult := 0.0;
{ BIFF Record header } { BIFF Record header }
@ -227,7 +253,7 @@ begin
AStream.WriteByte(RPNLength); AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos; AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(17 + RPNLength)); AStream.WriteWord(WordToLE(17 + RPNLength));
AStream.position := FinalPos; AStream.position := FinalPos;*)
end; end;
{******************************************************************* {*******************************************************************

View File

@ -97,7 +97,7 @@ type
procedure WriteDimensions(AStream: TStream); procedure WriteDimensions(AStream: TStream);
procedure WriteEOF(AStream: TStream); procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFont: TFPCustomFont); procedure WriteFont(AStream: TStream; AFont: TFPCustomFont);
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override; procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override;
procedure WriteIndex(AStream: TStream); procedure WriteIndex(AStream: TStream);
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override; procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
@ -536,14 +536,14 @@ end;
* *
*******************************************************************} *******************************************************************}
procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow, procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula); ACol: Word; const AFormula: TsFormula);
var {var
FormulaResult: double; FormulaResult: double;
i: Integer; i: Integer;
RPNLength: Word; RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Int64; TokenArraySizePos, RecordSizePos, FinalPos: Int64;}
begin begin
RPNLength := 0; (* RPNLength := 0;
FormulaResult := 0.0; FormulaResult := 0.0;
{ BIFF Record header } { BIFF Record header }
@ -612,7 +612,7 @@ begin
AStream.WriteByte(RPNLength); AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos; AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(22 + RPNLength)); AStream.WriteWord(WordToLE(22 + RPNLength));
AStream.position := FinalPos; AStream.position := FinalPos;*)
end; end;
{******************************************************************* {*******************************************************************

View File

@ -66,7 +66,7 @@ type
procedure WriteEOF(AStream: TStream); procedure WriteEOF(AStream: TStream);
procedure WriteFont(AStream: TStream; AFontName: Widestring = 'Arial'); procedure WriteFont(AStream: TStream; AFontName: Widestring = 'Arial');
procedure WriteFormat(AStream: TStream; AIndex: Word = 0; AFormatString: Widestring = 'General'); procedure WriteFormat(AStream: TStream; AIndex: Word = 0; AFormatString: Widestring = 'General');
procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TRPNFormula); override; procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override;
procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override; procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override;
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override;
procedure WriteXF(AStream: TStream); procedure WriteXF(AStream: TStream);
@ -260,14 +260,14 @@ end;
* *
*******************************************************************} *******************************************************************}
procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow, procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow,
ACol: Word; const AFormula: TRPNFormula); ACol: Word; const AFormula: TsFormula);
var {var
FormulaResult: double; FormulaResult: double;
i: Integer; i: Integer;
RPNLength: Word; RPNLength: Word;
TokenArraySizePos, RecordSizePos, FinalPos: Cardinal; TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;}
begin begin
RPNLength := 0; (* RPNLength := 0;
FormulaResult := 0.0; FormulaResult := 0.0;
{ BIFF Record header } { BIFF Record header }
@ -336,7 +336,7 @@ begin
AStream.WriteByte(RPNLength); AStream.WriteByte(RPNLength);
AStream.Position := RecordSizePos; AStream.Position := RecordSizePos;
AStream.WriteWord(WordToLE(17 + RPNLength)); AStream.WriteWord(WordToLE(17 + RPNLength));
AStream.position := FinalPos; AStream.position := FinalPos;*)
end; end;
{******************************************************************* {*******************************************************************

View File

@ -5,13 +5,13 @@ Writes an OOXML (Office Open XML) document
An OOXML document is a compressed ZIP file with the following files inside: An OOXML document is a compressed ZIP file with the following files inside:
[Content_Types].xml [Content_Types].xml -
_rels\.rels _rels\.rels -
xl\_rels\workbook.xml.rels xl\_rels\workbook.xml.rels -
xl\workbook.xml xl\workbook.xml - Global workbook data and list of worksheets
xl\styles.xml xl\styles.xml -
xl\sharedStrings.xml xl\sharedStrings.xml -
xl\worksheets\sheet1.xml xl\worksheets\sheet1.xml - Contents of each worksheet
... ...
xl\worksheets\sheetN.xml xl\worksheets\sheetN.xml
@ -20,8 +20,6 @@ Specifications obtained from:
http://openxmldeveloper.org/default.aspx http://openxmldeveloper.org/default.aspx
AUTHORS: Felipe Monteiro de Carvalho AUTHORS: Felipe Monteiro de Carvalho
IMPORTANT: This writer doesn't work yet!!! This is just initial code.
} }
unit xlsxooxml; unit xlsxooxml;
@ -32,7 +30,8 @@ unit xlsxooxml;
interface interface
uses uses
Classes, SysUtils, zipper, Classes, SysUtils,
fpszipper, {NOTE: fpszipper is the latest zipper.pp Change to standard zipper when FPC 2.4 is released }
fpspreadsheet; fpspreadsheet;
type type
@ -41,12 +40,23 @@ type
TsSpreadOOXMLWriter = class(TsCustomSpreadWriter) TsSpreadOOXMLWriter = class(TsCustomSpreadWriter)
protected protected
FZip: TZipper; { Strings with the contents of files }
FContentTypes: string; FContentTypes: string;
FRelsRels: string; FRelsRels: string;
FWorkbook, FWorkbookRels, FStyles, FSharedString, FSheet1: string; FWorkbook, FWorkbookRels, FStyles, FSharedStrings: string;
procedure FillFileContentStrings(AData: TsWorkbook); FSheets: array of string;
FSharedStringsCount: Integer;
{ Streams with the contents of files }
FSContentTypes: TStringStream;
FSRelsRels: TStringStream;
FSWorkbook, FSWorkbookRels, FSStyles, FSSharedStrings: TStringStream;
FSSheets: array of TStringStream;
{ Routines to write those files }
procedure WriteGlobalFiles;
procedure WriteContent(AData: TsWorkbook);
procedure WriteWorksheet(CurSheet: TsWorksheet);
public public
destructor Destroy; override;
{ General writing methods } { General writing methods }
procedure WriteStringToFile(AFileName, AString: string); procedure WriteStringToFile(AFileName, AString: string);
procedure WriteToFile(AFileName: string; AData: TsWorkbook); override; procedure WriteToFile(AFileName: string; AData: TsWorkbook); override;
@ -64,15 +74,15 @@ const
{ OOXML Directory structure constants } { OOXML Directory structure constants }
OOXML_PATH_TYPES = '[Content_Types].xml'; OOXML_PATH_TYPES = '[Content_Types].xml';
OOXML_PATH_RELS = '_rels\'; OOXML_PATH_RELS = '_rels' + PathDelim;
OOXML_PATH_RELS_RELS = '_rels\.rels'; OOXML_PATH_RELS_RELS = '_rels' + PathDelim + '.rels';
OOXML_PATH_XL = 'xl\'; OOXML_PATH_XL = 'xl' + PathDelim;
OOXML_PATH_XL_RELS = 'xl\_rels\'; OOXML_PATH_XL_RELS = 'xl' + PathDelim + '_rels' + PathDelim;
OOXML_PATH_XL_RELS_RELS = 'xl\_rels\workbook.xml.rels'; OOXML_PATH_XL_RELS_RELS = 'xl' + PathDelim + '_rels' + PathDelim + 'workbook.xml.rels';
OOXML_PATH_XL_WORKBOOK = 'xl\workbook.xml'; OOXML_PATH_XL_WORKBOOK = 'xl' + PathDelim + 'workbook.xml';
OOXML_PATH_XL_STYLES = 'xl\styles.xml'; OOXML_PATH_XL_STYLES = 'xl' + PathDelim + 'styles.xml';
OOXML_PATH_XL_STRINGS = 'xl\sharedStrings.xml'; OOXML_PATH_XL_STRINGS = 'xl' + PathDelim + 'sharedStrings.xml';
OOXML_PATH_XL_WORKSHEETS = 'xl\worksheets\'; OOXML_PATH_XL_WORKSHEETS = 'xl' + PathDelim + 'worksheets' + PathDelim;
{ OOXML schemas constants } { OOXML schemas constants }
SCHEMAS_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types'; SCHEMAS_TYPES = 'http://schemas.openxmlformats.org/package/2006/content-types';
@ -95,7 +105,7 @@ const
{ TsSpreadOOXMLWriter } { TsSpreadOOXMLWriter }
procedure TsSpreadOOXMLWriter.FillFileContentStrings(AData: TsWorkbook); procedure TsSpreadOOXMLWriter.WriteGlobalFiles;
begin begin
// WriteCellsToStream(AStream, AData.GetFirstWorksheet.FCells); // WriteCellsToStream(AStream, AData.GetFirstWorksheet.FCells);
@ -116,28 +126,6 @@ begin
'<Relationship Type="' + SCHEMAS_DOCUMENT + '" Target="/xl/workbook.xml" Id="rId1" />' + LineEnding + '<Relationship Type="' + SCHEMAS_DOCUMENT + '" Target="/xl/workbook.xml" Id="rId1" />' + LineEnding +
'</Relationships>'; '</Relationships>';
FWorkbookRels :=
XML_HEADER + LineEnding +
'<Relationships xmlns="' + SCHEMAS_RELS + '">' + LineEnding +
'<Relationship Type="' + SCHEMAS_WORKSHEET + '" Target="/xl/worksheets/sheet1.xml" Id="rId1" />' + LineEnding +
'<Relationship Type="' + SCHEMAS_STYLES + '" Target="/xl/styles.xml" Id="rId2" />' + LineEnding +
'<Relationship Type="' + SCHEMAS_STRINGS + '" Target="/xl/sharedStrings.xml" Id="rId3" />' + LineEnding +
'</Relationships>';
FWorkbook :=
XML_HEADER + LineEnding +
'<workbook xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding +
' <fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4505" />' + LineEnding +
' <workbookPr defaultThemeVersion="124226" />' + LineEnding +
' <bookViews>' + LineEnding +
' <workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" />' + LineEnding +
' </bookViews>' + LineEnding +
' <sheets>' + LineEnding +
' <sheet name="Sheet1" sheetId="1" r:id="rId1" />' + LineEnding +
' </sheets>' + LineEnding +
' <calcPr calcId="114210" />' + LineEnding +
'</workbook>';
FStyles := FStyles :=
XML_HEADER + LineEnding + XML_HEADER + LineEnding +
'<styleSheet xmlns="' + SCHEMAS_SPREADML + '">' + LineEnding + '<styleSheet xmlns="' + SCHEMAS_SPREADML + '">' + LineEnding +
@ -176,11 +164,71 @@ begin
' <dxfs count="0" />' + LineEnding + ' <dxfs count="0" />' + LineEnding +
' <tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleLight16" />' + LineEnding + ' <tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleLight16" />' + LineEnding +
'</styleSheet>'; '</styleSheet>';
end;
FSharedString := procedure TsSpreadOOXMLWriter.WriteContent(AData: TsWorkbook);
var
i: Integer;
begin
{ Workbook relations - Mark relation to all sheets }
FWorkbookRels :=
XML_HEADER + LineEnding + XML_HEADER + LineEnding +
'<sst xmlns="' + SCHEMAS_SPREADML + '" count="4" uniqueCount="4">' + LineEnding + '<Relationships xmlns="' + SCHEMAS_RELS + '">' + LineEnding +
' <si>' + LineEnding + '<Relationship Type="' + SCHEMAS_STYLES + '" Target="/xl/styles.xml" Id="rId1" />' + LineEnding +
'<Relationship Type="' + SCHEMAS_STRINGS + '" Target="/xl/sharedStrings.xml" Id="rId2" />' + LineEnding;
for i := 1 to AData.GetWorksheetCount do
begin
FWorkbookRels := FWorkbookRels +
'<Relationship Type="' + SCHEMAS_WORKSHEET + '" Target="/xl/worksheets/sheet' + IntToStr(i) +
'.xml" Id="rId' + IntToStr(i + 2) + '" />' + LineEnding;
end;
FWorkbookRels := FWorkbookRels +
'</Relationships>';
// Global workbook data - Mark all sheets
FWorkbook :=
XML_HEADER + LineEnding +
'<workbook xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding +
' <fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4505" />' + LineEnding +
' <workbookPr defaultThemeVersion="124226" />' + LineEnding +
' <bookViews>' + LineEnding +
' <workbookView xWindow="480" yWindow="90" windowWidth="15195" windowHeight="12525" />' + LineEnding +
' </bookViews>' + LineEnding;
for i := 1 to AData.GetWorksheetCount do
begin
FWorkbook := FWorkbook +
' <sheets>' + LineEnding +
' <sheet name="Sheet' + IntToStr(i) + '" sheetId="'
+ IntToStr(i) + '" r:id="rId' + IntToStr(i) + '" />' + LineEnding +
' </sheets>' + LineEnding;
end;
FWorkbook := FWorkbook +
' <calcPr calcId="114210" />' + LineEnding +
'</workbook>';
// Preparation for Shared strings
FSharedStringsCount := 0;
FSharedStrings := '';
// Write all worksheets, which fills also FSharedStrings
SetLength(FSheets, 0);
for i := 0 to AData.GetWorksheetCount - 1 do
begin
WriteWorksheet(Adata.GetWorksheetByIndex(i));
end;
// Finalization of the shared strings document
FSharedStrings :=
XML_HEADER + LineEnding +
'<sst xmlns="' + SCHEMAS_SPREADML + '" count="' + IntToStr(FSharedStringsCount) +
'" uniqueCount="' + IntToStr(FSharedStringsCount) + '">' + LineEnding +
FSharedStrings +
{ ' <si>' + LineEnding +
' <t>First</t>' + LineEnding + ' <t>First</t>' + LineEnding +
' </si>' + LineEnding + ' </si>' + LineEnding +
' <si>' + LineEnding + ' <si>' + LineEnding +
@ -191,10 +239,18 @@ begin
' </si>' + LineEnding + ' </si>' + LineEnding +
' <si>' + LineEnding + ' <si>' + LineEnding +
' <t>Fourth</t>' + LineEnding + ' <t>Fourth</t>' + LineEnding +
' </si>' + LineEnding + ' </si>' + LineEnding + }
'</sst>'; '</sst>';
end;
FSheet1 := procedure TsSpreadOOXMLWriter.WriteWorksheet(CurSheet: TsWorksheet);
var
CurStr: Integer;
begin
CurStr := Length(FSheets);
SetLength(FSheets, CurStr + 1);
FSheets[CurStr] :=
XML_HEADER + LineEnding + XML_HEADER + LineEnding +
'<worksheet xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding + '<worksheet xmlns="' + SCHEMAS_SPREADML + '" xmlns:r="' + SCHEMAS_DOC_RELS + '">' + LineEnding +
' <sheetViews>' + LineEnding + ' <sheetViews>' + LineEnding +
@ -228,17 +284,22 @@ begin
' <c r="D2" t="s">' + LineEnding + ' <c r="D2" t="s">' + LineEnding +
' <v>3</v>' + LineEnding + ' <v>3</v>' + LineEnding +
' </c>' + LineEnding + ' </c>' + LineEnding +
' </row>' + LineEnding + ' </row>' + LineEnding +
' </sheetData>' + LineEnding + ' </sheetData>' + LineEnding +
'</worksheet>'; '</worksheet>';
end; end;
{******************************************************************* destructor TsSpreadOOXMLWriter.Destroy;
* TsSpreadOOXMLWriter.WriteStringToFile () begin
* SetLength(FSheets, 0);
* DESCRIPTION: Writes a string to a file. Helper convenience method. SetLength(FSSheets, 0);
*
*******************************************************************} inherited Destroy;
end;
{
Writes a string to a file. Helper convenience method.
}
procedure TsSpreadOOXMLWriter.WriteStringToFile(AFileName, AString: string); procedure TsSpreadOOXMLWriter.WriteStringToFile(AFileName, AString: string);
var var
TheStream : TFileStream; TheStream : TFileStream;
@ -250,127 +311,92 @@ begin
TheStream.Free; TheStream.Free;
end; end;
{******************************************************************* {
* TsSpreadOOXMLWriter.WriteToFile () Writes an OOXML document to the disc
* }
* DESCRIPTION: Writes an OOXML document to the disc
*
*******************************************************************}
procedure TsSpreadOOXMLWriter.WriteToFile(AFileName: string; AData: TsWorkbook); procedure TsSpreadOOXMLWriter.WriteToFile(AFileName: string; AData: TsWorkbook);
var var
TempDir: string; FZip: TZipper;
i: Integer;
begin begin
{ FZip := TZipper.Create; { Fill the strings with the contents of the files }
FZip.ZipFiles(AFileName, x);
FZip.Free;}
FillFileContentStrings(AData);
TempDir := IncludeTrailingBackslash(AFileName); WriteGlobalFiles();
WriteContent(AData);
{ files on the root path } { Write the data to streams }
ForceDirectories(TempDir); FSContentTypes := TStringStream.Create(FContentTypes);
FSRelsRels := TStringStream.Create(FRelsRels);
FSWorkbookRels := TStringStream.Create(FWorkbookRels);
FSWorkbook := TStringStream.Create(FWorkbook);
FSStyles := TStringStream.Create(FStyles);
FSSharedStrings := TStringStream.Create(FSharedStrings);
WriteStringToFile(TempDir + OOXML_PATH_TYPES, FContentTypes); SetLength(FSSheets, Length(FSheets));
{ _rels directory }
ForceDirectories(TempDir + OOXML_PATH_RELS); for i := 0 to Length(FSheets) - 1 do
FSSheets[i] := TStringStream.Create(FSheets[i]);
WriteStringToFile(TempDir + OOXML_PATH_RELS_RELS, FRelsRels); { Now compress the files }
{ xl directory } FZip := TZipper.Create;
try
FZip.FileName := AFileName;
ForceDirectories(TempDir + OOXML_PATH_XL_RELS); FZip.Entries.AddFileEntry(FSContentTypes, OOXML_PATH_TYPES);
FZip.Entries.AddFileEntry(FSRelsRels, OOXML_PATH_RELS_RELS);
WriteStringToFile(TempDir + OOXML_PATH_XL_RELS_RELS, FWorkbookRels); FZip.Entries.AddFileEntry(FSWorkbookRels, OOXML_PATH_XL_RELS_RELS);
FZip.Entries.AddFileEntry(FSWorkbook, OOXML_PATH_XL_WORKBOOK);
WriteStringToFile(TempDir + OOXML_PATH_XL_WORKBOOK, FWorkbook); FZip.Entries.AddFileEntry(FSStyles, OOXML_PATH_XL_STYLES);
FZip.Entries.AddFileEntry(FSSharedStrings, OOXML_PATH_XL_STRINGS);
WriteStringToFile(TempDir + OOXML_PATH_XL_STYLES, FStyles); for i := 0 to Length(FSheets) - 1 do
FZip.Entries.AddFileEntry(FSSheets[i], OOXML_PATH_XL_WORKSHEETS + 'sheet' + IntToStr(i + 1) + '.xml');
WriteStringToFile(TempDir + OOXML_PATH_XL_STRINGS, FSharedString); FZip.ZipAllFiles;
finally
{ xl\worksheets directory } FSContentTypes.Free;
FSRelsRels.Free;
FSWorkbookRels.Free;
FSWorkbook.Free;
FSStyles.Free;
FSSharedStrings.Free;
ForceDirectories(TempDir + OOXML_PATH_XL_WORKSHEETS); for i := 0 to Length(FSSheets) - 1 do
FSSheets[i].Free;
WriteStringToFile(TempDir + OOXML_PATH_XL_WORKSHEETS + 'sheet1.xml', FSheet1); FZip.Free;
end;
end; end;
procedure TsSpreadOOXMLWriter.WriteToStream(AStream: TStream; AData: TsWorkbook); procedure TsSpreadOOXMLWriter.WriteToStream(AStream: TStream; AData: TsWorkbook);
begin begin
// Not supported at the moment
raise Exception.Create('TsSpreadOpenDocWriter.WriteToStream not supported');
end; end;
{******************************************************************* {
* TsSpreadOOXMLWriter.WriteLabel () Writes a string to the sheet
* }
* DESCRIPTION: Writes an Excel 2 LABEL record
*
* Writes a string to the sheet
*
*******************************************************************}
procedure TsSpreadOOXMLWriter.WriteLabel(AStream: TStream; const ARow, procedure TsSpreadOOXMLWriter.WriteLabel(AStream: TStream; const ARow,
ACol: Word; const AValue: string); ACol: Word; const AValue: string);
var
L: Byte;
begin begin
L := Length(AValue);
{ BIFF Record header }
// AStream.WriteWord(WordToLE(INT_EXCEL_ID_LABEL));
// AStream.WriteWord(WordToLE(8 + L));
{ BIFF Record data }
// AStream.WriteWord(WordToLE(ARow));
// AStream.WriteWord(WordToLE(ACol));
{ BIFF2 Attributes }
AStream.WriteByte($0);
AStream.WriteByte($0);
AStream.WriteByte($0);
{ String with 8-bit size }
AStream.WriteByte(L);
AStream.WriteBuffer(AValue[1], L);
end; end;
{******************************************************************* {
* TsSpreadOOXMLWriter.WriteNumber () Writes a number (64-bit IEE 754 floating point) to the sheet
* }
* DESCRIPTION: Writes an Excel 2 NUMBER record
*
* Writes a number (64-bit IEE 754 floating point) to the sheet
*
*******************************************************************}
procedure TsSpreadOOXMLWriter.WriteNumber(AStream: TStream; const ARow, procedure TsSpreadOOXMLWriter.WriteNumber(AStream: TStream; const ARow,
ACol: Cardinal; const AValue: double); ACol: Cardinal; const AValue: double);
begin begin
{ BIFF Record header }
// AStream.WriteWord(WordToLE(INT_EXCEL_ID_NUMBER));
// AStream.WriteWord(WordToLE(15));
{ BIFF Record data }
// AStream.WriteWord(WordToLE(ARow));
// AStream.WriteWord(WordToLE(ACol));
{ BIFF2 Attributes }
AStream.WriteByte($0);
AStream.WriteByte($0);
AStream.WriteByte($0);
{ IEE 754 floating-point value }
AStream.WriteBuffer(AValue, 8);
end; end;
{******************************************************************* {
* Initialization section Registers this reader / writer on fpSpreadsheet
* }
* Registers this reader / writer on fpSpreadsheet
*
*******************************************************************}
initialization initialization
RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadOOXMLWriter, sfOOXML); RegisterSpreadFormat(TsCustomSpreadReader, TsSpreadOOXMLWriter, sfOOXML);