diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpi b/components/fpspreadsheet/examples/excel5demo/excel5write.lpi index eb6ea9847..c2e02c20b 100644 --- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpi +++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpi @@ -11,7 +11,7 @@ <UseAppBundle Value="False"/> - <ActiveEditorIndexAtStart Value="3"/> + <ActiveEditorIndexAtStart Value="1"/> </General> <VersionInfo> <ProjectVersion Value=""/> @@ -38,8 +38,8 @@ <Filename Value="excel5write.lpr"/> <IsPartOfProject Value="True"/> <UnitName Value="excel5write"/> - <CursorPos X="36" Y="32"/> - <TopLine Value="26"/> + <CursorPos X="25" Y="56"/> + <TopLine Value="37"/> <EditorIndex Value="0"/> <UsageCount Value="309"/> <Loaded Value="True"/> @@ -68,8 +68,8 @@ <Unit4> <Filename Value="..\..\xlsbiff5.pas"/> <UnitName Value="xlsbiff5"/> - <CursorPos X="1" Y="1063"/> - <TopLine Value="1047"/> + <CursorPos X="1" Y="1"/> + <TopLine Value="1"/> <EditorIndex Value="3"/> <UsageCount Value="140"/> <Loaded Value="True"/> @@ -86,8 +86,8 @@ <Unit6> <Filename Value="..\..\xlsbiff2.pas"/> <UnitName Value="xlsbiff2"/> - <CursorPos X="34" Y="256"/> - <TopLine Value="236"/> + <CursorPos X="1" Y="286"/> + <TopLine Value="275"/> <EditorIndex Value="6"/> <UsageCount Value="139"/> <Loaded Value="True"/> @@ -116,8 +116,8 @@ <Unit10> <Filename Value="..\..\fpspreadsheet.pas"/> <UnitName Value="fpspreadsheet"/> - <CursorPos X="1" Y="13"/> - <TopLine Value="12"/> + <CursorPos X="79" Y="836"/> + <TopLine Value="819"/> <EditorIndex Value="1"/> <UsageCount Value="92"/> <Loaded Value="True"/> @@ -150,123 +150,123 @@ <JumpHistory Count="30" HistoryIndex="29"> <Position1> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="405" Column="5" TopLine="386"/> + <Caret Line="314" Column="39" TopLine="296"/> </Position1> <Position2> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="404" Column="14" TopLine="401"/> + <Caret Line="479" Column="1" TopLine="469"/> </Position2> <Position3> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="79" Column="42" TopLine="72"/> + <Caret Line="470" Column="1" TopLine="460"/> </Position3> <Position4> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="78" Column="31" TopLine="67"/> + <Filename Value="..\..\xlsbiff5.pas"/> + <Caret Line="217" Column="3" TopLine="205"/> </Position4> <Position5> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="314" Column="39" TopLine="296"/> + <Filename Value="..\..\xlsbiff5.pas"/> + <Caret Line="218" Column="23" TopLine="208"/> </Position5> <Position6> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="479" Column="1" TopLine="469"/> + <Caret Line="78" Column="10" TopLine="66"/> </Position6> <Position7> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="470" Column="1" TopLine="460"/> + <Caret Line="375" Column="1" TopLine="367"/> </Position7> <Position8> - <Filename Value="..\..\xlsbiff5.pas"/> - <Caret Line="217" Column="3" TopLine="205"/> + <Filename Value="..\..\fpolestorage.pas"/> + <Caret Line="76" Column="17" TopLine="65"/> </Position8> <Position9> - <Filename Value="..\..\xlsbiff5.pas"/> - <Caret Line="218" Column="23" TopLine="208"/> + <Filename Value="..\..\fpolestorage.pas"/> + <Caret Line="363" Column="1" TopLine="357"/> </Position9> <Position10> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="78" Column="10" TopLine="66"/> + <Caret Line="77" Column="7" TopLine="76"/> </Position10> <Position11> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="375" Column="1" TopLine="367"/> + <Filename Value="..\..\fpspreadsheet.pas"/> + <Caret Line="137" Column="40" TopLine="129"/> </Position11> <Position12> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="76" Column="17" TopLine="65"/> + <Caret Line="563" Column="5" TopLine="544"/> </Position12> <Position13> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="363" Column="1" TopLine="357"/> + <Caret Line="486" Column="5" TopLine="467"/> </Position13> <Position14> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="77" Column="7" TopLine="76"/> + <Caret Line="510" Column="5" TopLine="491"/> </Position14> <Position15> - <Filename Value="..\..\fpspreadsheet.pas"/> - <Caret Line="137" Column="40" TopLine="129"/> + <Filename Value="..\..\fpolestorage.pas"/> + <Caret Line="94" Column="46" TopLine="84"/> </Position15> <Position16> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="563" Column="5" TopLine="544"/> + <Caret Line="686" Column="5" TopLine="667"/> </Position16> <Position17> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="486" Column="5" TopLine="467"/> + <Caret Line="567" Column="5" TopLine="548"/> </Position17> <Position18> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="510" Column="5" TopLine="491"/> + <Caret Line="622" Column="1" TopLine="618"/> </Position18> <Position19> <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="94" Column="46" TopLine="84"/> + <Caret Line="621" Column="29" TopLine="611"/> </Position19> <Position20> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="686" Column="5" TopLine="667"/> - </Position20> - <Position21> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="567" Column="5" TopLine="548"/> - </Position21> - <Position22> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="622" Column="1" TopLine="618"/> - </Position22> - <Position23> - <Filename Value="..\..\fpolestorage.pas"/> - <Caret Line="621" Column="29" TopLine="611"/> - </Position23> - <Position24> <Filename Value="..\..\xlsbiff5.pas"/> <Caret Line="100" Column="17" TopLine="92"/> - </Position24> - <Position25> + </Position20> + <Position21> <Filename Value="..\..\xlsbiff5.pas"/> <Caret Line="615" Column="34" TopLine="593"/> - </Position25> - <Position26> + </Position21> + <Position22> <Filename Value="..\..\fpsopendocument.pas"/> <Caret Line="1" Column="1" TopLine="1"/> - </Position26> - <Position27> + </Position22> + <Position23> <Filename Value="..\..\fpsopendocument.pas"/> <Caret Line="56" Column="88" TopLine="43"/> - </Position27> - <Position28> + </Position23> + <Position24> <Filename Value="..\..\xlsbiff8.pas"/> <Caret Line="1" Column="1" TopLine="1"/> - </Position28> - <Position29> + </Position24> + <Position25> <Filename Value="..\..\xlsbiff8.pas"/> <Caret Line="69" Column="88" TopLine="56"/> + </Position25> + <Position26> + <Filename Value="excel5write.lpr"/> + <Caret Line="47" Column="30" TopLine="33"/> + </Position26> + <Position27> + <Filename Value="excel5write.lpr"/> + <Caret Line="53" Column="21" TopLine="40"/> + </Position27> + <Position28> + <Filename Value="excel5write.lpr"/> + <Caret Line="54" Column="27" TopLine="40"/> + </Position28> + <Position29> + <Filename Value="excel5write.lpr"/> + <Caret Line="52" Column="38" TopLine="43"/> </Position29> <Position30> <Filename Value="excel5write.lpr"/> - <Caret Line="47" Column="30" TopLine="33"/> + <Caret Line="56" Column="25" TopLine="37"/> </Position30> </JumpHistory> </ProjectOptions> diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr index db6d9426b..71d8e02a4 100644 --- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr +++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr @@ -16,7 +16,7 @@ uses var MyWorkbook: TsWorkbook; MyWorksheet: TsWorksheet; - MyFormula: TsFormula; + MyRPNFormula: TsRPNFormula; MyDir: string; i: Integer; begin @@ -45,8 +45,17 @@ begin } // Write the formula E1 = A1 + B1 -// MyFormula.FormulaStr := ''; -// MyWorksheet.WriteFormula(0, 4, MyFormula); + SetLength(MyRPNFormula, 3); + MyRPNFormula[0].ElementKind := fekCell; + MyRPNFormula[0].Col := 0; + MyRPNFormula[0].Row := 0; + MyRPNFormula[1].ElementKind := fekCell; + MyRPNFormula[1].Col := 1; + MyRPNFormula[1].Row := 0; + MyRPNFormula[2].ElementKind := fekAdd; + MyWorksheet.WriteRPNFormula(0, 4, MyRPNFormula); + + //MyFormula.FormulaStr := ''; // Creates a new worksheet MyWorksheet := MyWorkbook.AddWorksheet('My Worksheet 2'); diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index b1ffe73fa..800555874 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -49,24 +49,31 @@ type TsFormulaElement = record ElementKind: TFEKind; - Row1, Row2: Word; - Col1, Col2: Byte; + Row, Row2: Word; // zero-based + Col, Col2: Byte; // zero-based DoubleValue: double; end; TsExpandedFormula = array of TsFormulaElement; + {@@ RPN formula. Similar to the expanded formula, but in RPN notation. + Simplifies the task of format writers which need RPN } + + TsRPNFormula = array of TsFormulaElement; + {@@ Describes the type of content of a cell on a TsWorksheet } - TCellContentType = (cctEmpty, cctFormula, cctNumber, cctUTF8String); + TCellContentType = (cctEmpty, cctFormula, cctRPNFormula, cctNumber, cctUTF8String); {@@ Cell structure for TsWorksheet } TCell = record - Col: Byte; - Row: Word; + Col: Byte; // zero-based + Row: Word; // zero-based ContentType: TCellContentType; + { Possible values for the cells } FormulaValue: TsFormula; + RPNFormulaValue: TsRPNFormula; NumberValue: double; UTF8StringValue: ansistring; end; @@ -101,6 +108,7 @@ type procedure WriteUTF8Text(ARow, ACol: Cardinal; AText: ansistring); procedure WriteNumber(ARow, ACol: Cardinal; ANumber: double); procedure WriteFormula(ARow, ACol: Cardinal; AFormula: TsFormula); + procedure WriteRPNFormula(ARow, ACol: Cardinal; AFormula: TsRPNFormula); end; { TsWorkbook } @@ -165,7 +173,8 @@ type procedure WriteToFile(AFileName: string; AData: TsWorkbook); virtual; procedure WriteToStream(AStream: TStream; AData: TsWorkbook); virtual; { Record writing methods } - procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); virtual; abstract; + procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); virtual; + procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsRPNFormula); virtual; 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; end; @@ -500,6 +509,17 @@ begin ACell^.FormulaValue := AFormula; end; +procedure TsWorksheet.WriteRPNFormula(ARow, ACol: Cardinal; + AFormula: TsRPNFormula); +var + ACell: PCell; +begin + ACell := GetCell(ARow, ACol); + + ACell^.ContentType := cctRPNFormula; + ACell^.RPNFormulaValue := AFormula; +end; + { TsWorkbook } {@@ @@ -810,9 +830,10 @@ begin AStream := TStream(arg); case ACell.ContentType of - cctFormula: WriteFormula(AStream, ACell^.Row, ACell^.Col, ACell^.FormulaValue); cctNumber: WriteNumber(AStream, ACell^.Row, ACell^.Col, ACell^.NumberValue); cctUTF8String: WriteLabel(AStream, ACell^.Row, ACell^.Col, ACell^.UTF8StringValue); + cctFormula: WriteFormula(AStream, ACell^.Row, ACell^.Col, ACell^.FormulaValue); + cctRPNFormula: WriteRPNFormula(AStream, ACell^.Row, ACell^.Col, ACell^.RPNFormulaValue); end; end; @@ -861,6 +882,18 @@ begin end; +procedure TsCustomSpreadWriter.WriteFormula(AStream: TStream; const ARow, + ACol: Word; const AFormula: TsFormula); +begin + +end; + +procedure TsCustomSpreadWriter.WriteRPNFormula(AStream: TStream; const ARow, + ACol: Word; const AFormula: TsRPNFormula); +begin + +end; + finalization SetLength(GsSpreadFormats, 0); diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 0aa06c860..bc824b75d 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -53,13 +53,15 @@ type { TsSpreadBIFF2Writer } TsSpreadBIFF2Writer = class(TsCustomSpreadWriter) + private + function FEKindToExcelID(AElement: TFEKind): Byte; public { General writing methods } procedure WriteToStream(AStream: TStream; AData: TsWorkbook); override; { Record writing methods } procedure WriteBOF(AStream: TStream); procedure WriteEOF(AStream: TStream); - procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override; + procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsRPNFormula); 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; end; @@ -84,17 +86,6 @@ const INT_EXCEL_CHART = $0020; 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 } @@ -115,6 +106,17 @@ const { TsSpreadBIFF2Writer } +function TsSpreadBIFF2Writer.FEKindToExcelID(AElement: TFEKind): Byte; +begin + case AElement of + fekCell: Result := INT_EXCEL_TOKEN_TREFV; + fekAdd: Result := INT_EXCEL_TOKEN_TADD; + fekSub: Result := INT_EXCEL_TOKEN_TSUB; + fekDiv: Result := INT_EXCEL_TOKEN_TDIV; + fekMul: Result := INT_EXCEL_TOKEN_TMUL; + end; +end; + { Writes an Excel 2 file to a stream @@ -176,15 +178,16 @@ end; MyFormula[1].Row := 0; MyFormula[2].TokenID := INT_EXCEL_TOKEN_TADD; + } -procedure TsSpreadBIFF2Writer.WriteFormula(AStream: TStream; const ARow, - ACol: Word; const AFormula: TsFormula); -{var +procedure TsSpreadBIFF2Writer.WriteRPNFormula(AStream: TStream; const ARow, + ACol: Word; const AFormula: TsRPNFormula); +var FormulaResult: double; i: Integer; RPNLength: Word; - TokenArraySizePos, RecordSizePos, FinalPos: Cardinal;} + TokenArraySizePos, RecordSizePos, FinalPos: Cardinal; + FormulaKind: Byte; begin -(* RPNLength := 0; + RPNLength := 0; FormulaResult := 0.0; { BIFF Record header } @@ -220,11 +223,12 @@ begin for i := 0 to Length(AFormula) - 1 do begin { Token identifier } - AStream.WriteByte(AFormula[i].TokenID); + FormulaKind := FEKindToExcelID(AFormula[i].ElementKind); + AStream.WriteByte(FormulaKind); Inc(RPNLength); { Additional data } - case AFormula[i].TokenID of + case FormulaKind of { binary operation tokens } @@ -253,7 +257,7 @@ begin AStream.WriteByte(RPNLength); AStream.Position := RecordSizePos; AStream.WriteWord(WordToLE(17 + RPNLength)); - AStream.position := FinalPos;*) + AStream.position := FinalPos; end; {******************************************************************* diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 08558269a..c878dd133 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -97,6 +97,8 @@ type { TsSpreadBIFF5Writer } TsSpreadBIFF5Writer = class(TsCustomSpreadWriter) + private + function FEKindToExcelID(AElement: TFEKind): Byte; public // constructor Create; // destructor Destroy; override; @@ -109,7 +111,7 @@ type procedure WriteDimensions(AStream: TStream); procedure WriteEOF(AStream: TStream); procedure WriteFont(AStream: TStream; AFont: TFPCustomFont); - procedure WriteFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsFormula); override; + procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Word; const AFormula: TsRPNFormula); override; procedure WriteIndex(AStream: TStream); procedure WriteLabel(AStream: TStream; const ARow, ACol: Word; const AValue: string); override; procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal; const AValue: double); override; @@ -220,12 +222,41 @@ const MASK_XF_VERT_ALIGN = $70; +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; + { Exported functions } { TsSpreadBIFF5Writer } +function TsSpreadBIFF5Writer.FEKindToExcelID(AElement: TFEKind): Byte; +begin + case AElement of + fekCell: Result := INT_EXCEL_TOKEN_TREFV; + fekAdd: Result := INT_EXCEL_TOKEN_TADD; + fekSub: Result := INT_EXCEL_TOKEN_TSUB; + fekDiv: Result := INT_EXCEL_TOKEN_TDIV; + fekMul: Result := INT_EXCEL_TOKEN_TMUL; + end; +end; + {******************************************************************* * TsSpreadBIFF5Writer.WriteToFile () * @@ -550,15 +581,16 @@ end; * AFormula array * *******************************************************************} -procedure TsSpreadBIFF5Writer.WriteFormula(AStream: TStream; const ARow, - ACol: Word; const AFormula: TsFormula); -{var +procedure TsSpreadBIFF5Writer.WriteRPNFormula(AStream: TStream; const ARow, + ACol: Word; const AFormula: TsRPNFormula); +var FormulaResult: double; i: Integer; RPNLength: Word; - TokenArraySizePos, RecordSizePos, FinalPos: Int64;} + TokenArraySizePos, RecordSizePos, FinalPos: Int64; + FormulaKind: Byte; begin -(* RPNLength := 0; + RPNLength := 0; FormulaResult := 0.0; { BIFF Record header } @@ -594,11 +626,12 @@ begin for i := 0 to Length(AFormula) - 1 do begin { Token identifier } - AStream.WriteByte(AFormula[i].TokenID); + FormulaKind := FEKindToExcelID(AFormula[i].ElementKind); + AStream.WriteByte(FormulaKind); Inc(RPNLength); { Additional data } - case AFormula[i].TokenID of + case FormulaKind of { binary operation tokens } @@ -627,7 +660,7 @@ begin AStream.WriteByte(RPNLength); AStream.Position := RecordSizePos; AStream.WriteWord(WordToLE(22 + RPNLength)); - AStream.position := FinalPos;*) + AStream.position := FinalPos; end; {*******************************************************************