You've already forked lazarus-ccr
fpspreadsheet: Implement number/datetime format support for BIFF5 reading/writing (like BIFF8)
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2979 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@@ -26,6 +26,7 @@ var
|
|||||||
MyRPNFormula: TsRPNFormula;
|
MyRPNFormula: TsRPNFormula;
|
||||||
MyDir: string;
|
MyDir: string;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
|
number: Double;
|
||||||
begin
|
begin
|
||||||
MyDir := ExtractFilePath(ParamStr(0));
|
MyDir := ExtractFilePath(ParamStr(0));
|
||||||
|
|
||||||
@@ -117,6 +118,64 @@ begin
|
|||||||
MyRPNFormula[1].ElementKind := fekABS;
|
MyRPNFormula[1].ElementKind := fekABS;
|
||||||
MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);
|
MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);
|
||||||
|
|
||||||
|
// Write current date/time to cells B11:B16
|
||||||
|
MyWorksheet.WriteUTF8Text(10, 0, 'nfShortDate');
|
||||||
|
MyWorksheet.WriteDateTime(10, 1, now, nfShortDate);
|
||||||
|
MyWorksheet.WriteUTF8Text(11, 0, 'nfShortTime');
|
||||||
|
MyWorksheet.WriteDateTime(11, 1, now, nfShortTime);
|
||||||
|
MyWorksheet.WriteUTF8Text(12, 0, 'nfLongTime');
|
||||||
|
MyWorksheet.WriteDateTime(12, 1, now, nfLongTime);
|
||||||
|
MyWorksheet.WriteUTF8Text(13, 0, 'nfShortDateTime');
|
||||||
|
MyWorksheet.WriteDateTime(13, 1, now, nfShortDateTime);
|
||||||
|
MyWorksheet.WriteUTF8Text(14, 0, 'nfFmtDateTime, DM');
|
||||||
|
MyWorksheet.WriteDateTime(14, 1, now, nfFmtDateTime, 'DM');
|
||||||
|
MyWorksheet.WriteUTF8Text(15, 0, 'nfFmtDateTime, MY');
|
||||||
|
MyWorksheet.WriteDateTime(15, 1, now, nfFmtDateTime, 'MY');
|
||||||
|
MyWorksheet.WriteUTF8Text(16, 0, 'nfShortTimeAM');
|
||||||
|
MyWorksheet.WriteDateTime(16, 1, now, nfShortTimeAM);
|
||||||
|
MyWorksheet.WriteUTF8Text(17, 0, 'nfLongTimeAM');
|
||||||
|
MyWorksheet.WriteDateTime(17, 1, now, nfLongTimeAM);
|
||||||
|
MyWorksheet.WriteUTF8Text(18, 0, 'nfFmtDateTime, MS');
|
||||||
|
MyWorksheet.WriteDateTime(18, 1, now, nfFmtDateTime, 'MS');
|
||||||
|
MyWorksheet.WriteUTF8Text(19, 0, 'nfFmtDateTime, MSZ');
|
||||||
|
MyWorksheet.WriteDateTime(19, 1, now, nfFmtDateTime, 'MSZ');
|
||||||
|
|
||||||
|
// Write formatted numbers
|
||||||
|
number := 12345.67890123456789;
|
||||||
|
MyWorksheet.WriteUTF8Text(24, 1, '12345.67890123456789');
|
||||||
|
MyWorksheet.WriteUTF8Text(24, 2, '-12345.67890123456789');
|
||||||
|
MyWorksheet.WriteUTF8Text(25, 0, 'nfFixed, 0 decs');
|
||||||
|
MyWorksheet.WriteNumber(25, 1, number, nfFixed, 0);
|
||||||
|
MyWorksheet.WriteNumber(25, 2, -number, nfFixed, 0);
|
||||||
|
MyWorksheet.WriteUTF8Text(26, 0, 'nfFixed, 2 decs');
|
||||||
|
MyWorksheet.WriteNumber(26, 1, number, nfFixed, 2);
|
||||||
|
MyWorksheet.WriteNumber(26, 2, -number, nfFixed, 2);
|
||||||
|
MyWorksheet.WriteUTF8Text(27, 0, 'nfFixedTh, 0 decs');
|
||||||
|
MyWorksheet.WriteNumber(27, 1, number, nfFixedTh, 0);
|
||||||
|
MyWorksheet.WriteNumber(27, 2, -number, nfFixedTh, 0);
|
||||||
|
MyWorksheet.WriteUTF8Text(28, 0, 'nfFixedTh, 2 decs');
|
||||||
|
MyWorksheet.WriteNumber(28, 1, number, nfFixedTh, 2);
|
||||||
|
MyWorksheet.WriteNumber(28, 2, -number, nfFixedTh, 2);
|
||||||
|
MyWorksheet.WriteUTF8Text(29, 0, 'nfSci, 1 dec');
|
||||||
|
MyWorksheet.WriteNumber(29, 1, number, nfSci);
|
||||||
|
MyWorksheet.WriteNumber(29, 2, -number, nfSci);
|
||||||
|
MyWorksheet.WriteNumber(29, 3, 1.0/number, nfSci);
|
||||||
|
MyWorksheet.WriteNumber(29, 4, -1.0/number, nfSci);
|
||||||
|
MyWorksheet.WriteUTF8Text(30, 0, 'nfExp, 2 decs');
|
||||||
|
MyWorksheet.WriteNumber(30, 1, number, nfExp, 2);
|
||||||
|
MyWorksheet.WriteNumber(30, 2, -number, nfExp, 2);
|
||||||
|
MyWorksheet.WriteNumber(30, 3, 1.0/number, nfExp, 2);
|
||||||
|
MyWorksheet.WriteNumber(30, 4, -1.0/number, nfExp, 2);
|
||||||
|
|
||||||
|
number := 1.333333333;
|
||||||
|
MyWorksheet.WriteUTF8Text(35, 0, 'nfPercentage, 0 decs');
|
||||||
|
MyWorksheet.WriteNumber(35, 1, number, nfPercentage, 0);
|
||||||
|
MyWorksheet.WriteUTF8Text(36, 0, 'nfPercentage, 2 decs');
|
||||||
|
MyWorksheet.WriteNumber(36, 1, number, nfPercentage, 2);
|
||||||
|
MyWorksheet.WriteUTF8Text(37, 0, 'nfTimeInterval');
|
||||||
|
MyWorksheet.WriteDateTime(37, 1, number, nfTimeInterval);
|
||||||
|
|
||||||
|
|
||||||
//MyFormula.FormulaStr := '';
|
//MyFormula.FormulaStr := '';
|
||||||
|
|
||||||
// Creates a new worksheet
|
// Creates a new worksheet
|
||||||
|
@@ -117,7 +117,7 @@
|
|||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="1"/>
|
<TopLine Value="1"/>
|
||||||
<CursorPos X="10" Y="7"/>
|
<CursorPos X="10" Y="7"/>
|
||||||
<UsageCount Value="120"/>
|
<UsageCount Value="122"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit0>
|
</Unit0>
|
||||||
<Unit1>
|
<Unit1>
|
||||||
@@ -127,12 +127,11 @@
|
|||||||
<HasResources Value="True"/>
|
<HasResources Value="True"/>
|
||||||
<ResourceBaseClass Value="Form"/>
|
<ResourceBaseClass Value="Form"/>
|
||||||
<UnitName Value="mainform"/>
|
<UnitName Value="mainform"/>
|
||||||
<IsVisibleTab Value="True"/>
|
|
||||||
<EditorIndex Value="1"/>
|
<EditorIndex Value="1"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="47"/>
|
<TopLine Value="43"/>
|
||||||
<CursorPos X="51" Y="49"/>
|
<CursorPos X="38" Y="63"/>
|
||||||
<UsageCount Value="120"/>
|
<UsageCount Value="122"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
<LoadedDesigner Value="True"/>
|
<LoadedDesigner Value="True"/>
|
||||||
</Unit1>
|
</Unit1>
|
||||||
@@ -143,7 +142,7 @@
|
|||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="2720"/>
|
<TopLine Value="2720"/>
|
||||||
<CursorPos X="49" Y="2742"/>
|
<CursorPos X="49" Y="2742"/>
|
||||||
<UsageCount Value="59"/>
|
<UsageCount Value="60"/>
|
||||||
<Bookmarks Count="1">
|
<Bookmarks Count="1">
|
||||||
<Item0 X="1" Y="1293" ID="1"/>
|
<Item0 X="1" Y="1293" ID="1"/>
|
||||||
</Bookmarks>
|
</Bookmarks>
|
||||||
@@ -156,7 +155,7 @@
|
|||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="257"/>
|
<TopLine Value="257"/>
|
||||||
<CursorPos X="34" Y="260"/>
|
<CursorPos X="34" Y="260"/>
|
||||||
<UsageCount Value="60"/>
|
<UsageCount Value="61"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit3>
|
</Unit3>
|
||||||
<Unit4>
|
<Unit4>
|
||||||
@@ -237,7 +236,7 @@
|
|||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="35"/>
|
<TopLine Value="35"/>
|
||||||
<CursorPos X="1" Y="62"/>
|
<CursorPos X="1" Y="62"/>
|
||||||
<UsageCount Value="35"/>
|
<UsageCount Value="36"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit13>
|
</Unit13>
|
||||||
<Unit14>
|
<Unit14>
|
||||||
@@ -265,11 +264,12 @@
|
|||||||
<Unit17>
|
<Unit17>
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
<UnitName Value="xlsbiff8"/>
|
<UnitName Value="xlsbiff8"/>
|
||||||
|
<IsVisibleTab Value="True"/>
|
||||||
<EditorIndex Value="6"/>
|
<EditorIndex Value="6"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="185"/>
|
<TopLine Value="1988"/>
|
||||||
<CursorPos X="1" Y="203"/>
|
<CursorPos X="35" Y="2068"/>
|
||||||
<UsageCount Value="34"/>
|
<UsageCount Value="35"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit17>
|
</Unit17>
|
||||||
<Unit18>
|
<Unit18>
|
||||||
@@ -292,9 +292,9 @@
|
|||||||
<UnitName Value="xlscommon"/>
|
<UnitName Value="xlscommon"/>
|
||||||
<EditorIndex Value="5"/>
|
<EditorIndex Value="5"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="493"/>
|
<TopLine Value="806"/>
|
||||||
<CursorPos X="16" Y="514"/>
|
<CursorPos X="3" Y="812"/>
|
||||||
<UsageCount Value="30"/>
|
<UsageCount Value="31"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit20>
|
</Unit20>
|
||||||
<Unit21>
|
<Unit21>
|
||||||
@@ -302,9 +302,9 @@
|
|||||||
<UnitName Value="xlsbiff5"/>
|
<UnitName Value="xlsbiff5"/>
|
||||||
<EditorIndex Value="7"/>
|
<EditorIndex Value="7"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="124"/>
|
<TopLine Value="1902"/>
|
||||||
<CursorPos X="38" Y="143"/>
|
<CursorPos X="3" Y="1921"/>
|
||||||
<UsageCount Value="17"/>
|
<UsageCount Value="18"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit21>
|
</Unit21>
|
||||||
<Unit22>
|
<Unit22>
|
||||||
@@ -312,9 +312,9 @@
|
|||||||
<UnitName Value="xlsbiff2"/>
|
<UnitName Value="xlsbiff2"/>
|
||||||
<EditorIndex Value="8"/>
|
<EditorIndex Value="8"/>
|
||||||
<WindowIndex Value="0"/>
|
<WindowIndex Value="0"/>
|
||||||
<TopLine Value="82"/>
|
<TopLine Value="1061"/>
|
||||||
<CursorPos X="38" Y="101"/>
|
<CursorPos X="3" Y="1057"/>
|
||||||
<UsageCount Value="18"/>
|
<UsageCount Value="19"/>
|
||||||
<Loaded Value="True"/>
|
<Loaded Value="True"/>
|
||||||
</Unit22>
|
</Unit22>
|
||||||
<Unit23>
|
<Unit23>
|
||||||
@@ -351,124 +351,124 @@
|
|||||||
</Units>
|
</Units>
|
||||||
<JumpHistory Count="30" HistoryIndex="29">
|
<JumpHistory Count="30" HistoryIndex="29">
|
||||||
<Position1>
|
<Position1>
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
||||||
<Caret Line="2500" Column="1" TopLine="2472"/>
|
<Caret Line="272" Column="1" TopLine="246"/>
|
||||||
</Position1>
|
</Position1>
|
||||||
<Position2>
|
<Position2>
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
||||||
<Caret Line="2504" Column="1" TopLine="2473"/>
|
<Caret Line="273" Column="1" TopLine="246"/>
|
||||||
</Position2>
|
</Position2>
|
||||||
<Position3>
|
<Position3>
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
<Caret Line="2505" Column="1" TopLine="2474"/>
|
<Caret Line="2482" Column="52" TopLine="2482"/>
|
||||||
</Position3>
|
</Position3>
|
||||||
<Position4>
|
<Position4>
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
<Caret Line="2508" Column="5" TopLine="2477"/>
|
<Caret Line="1" Column="1" TopLine="1"/>
|
||||||
</Position4>
|
</Position4>
|
||||||
<Position5>
|
<Position5>
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
||||||
<Caret Line="263" Column="21" TopLine="244"/>
|
<Caret Line="273" Column="35" TopLine="212"/>
|
||||||
</Position5>
|
</Position5>
|
||||||
<Position6>
|
<Position6>
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="265" Column="1" TopLine="220"/>
|
|
||||||
</Position6>
|
|
||||||
<Position7>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="271" Column="1" TopLine="252"/>
|
|
||||||
</Position7>
|
|
||||||
<Position8>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="272" Column="1" TopLine="252"/>
|
|
||||||
</Position8>
|
|
||||||
<Position9>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="273" Column="1" TopLine="252"/>
|
|
||||||
</Position9>
|
|
||||||
<Position10>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="274" Column="1" TopLine="252"/>
|
|
||||||
</Position10>
|
|
||||||
<Position11>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="265" Column="1" TopLine="246"/>
|
|
||||||
</Position11>
|
|
||||||
<Position12>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="271" Column="1" TopLine="246"/>
|
|
||||||
</Position12>
|
|
||||||
<Position13>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="272" Column="1" TopLine="246"/>
|
|
||||||
</Position13>
|
|
||||||
<Position14>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="273" Column="1" TopLine="246"/>
|
|
||||||
</Position14>
|
|
||||||
<Position15>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="274" Column="1" TopLine="246"/>
|
|
||||||
</Position15>
|
|
||||||
<Position16>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="265" Column="1" TopLine="246"/>
|
|
||||||
</Position16>
|
|
||||||
<Position17>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="271" Column="1" TopLine="246"/>
|
|
||||||
</Position17>
|
|
||||||
<Position18>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="272" Column="1" TopLine="246"/>
|
|
||||||
</Position18>
|
|
||||||
<Position19>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="273" Column="1" TopLine="246"/>
|
|
||||||
</Position19>
|
|
||||||
<Position20>
|
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
|
||||||
<Caret Line="2482" Column="52" TopLine="2482"/>
|
|
||||||
</Position20>
|
|
||||||
<Position21>
|
|
||||||
<Filename Value="..\..\xlsbiff8.pas"/>
|
|
||||||
<Caret Line="1" Column="1" TopLine="1"/>
|
|
||||||
</Position21>
|
|
||||||
<Position22>
|
|
||||||
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
|
|
||||||
<Caret Line="273" Column="35" TopLine="212"/>
|
|
||||||
</Position22>
|
|
||||||
<Position23>
|
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="189" Column="35" TopLine="189"/>
|
<Caret Line="189" Column="35" TopLine="189"/>
|
||||||
</Position23>
|
</Position6>
|
||||||
<Position24>
|
<Position7>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="1" Column="1" TopLine="1"/>
|
<Caret Line="1" Column="1" TopLine="1"/>
|
||||||
</Position24>
|
</Position7>
|
||||||
<Position25>
|
<Position8>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="421" Column="17" TopLine="391"/>
|
<Caret Line="421" Column="17" TopLine="391"/>
|
||||||
</Position25>
|
</Position8>
|
||||||
<Position26>
|
<Position9>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="2154" Column="6" TopLine="2154"/>
|
<Caret Line="2154" Column="6" TopLine="2154"/>
|
||||||
</Position26>
|
</Position9>
|
||||||
<Position27>
|
<Position10>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="1" Column="1" TopLine="1"/>
|
<Caret Line="1" Column="1" TopLine="1"/>
|
||||||
</Position27>
|
</Position10>
|
||||||
<Position28>
|
<Position11>
|
||||||
<Filename Value="..\..\xlsbiff5.pas"/>
|
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||||
<Caret Line="1581" Column="39" TopLine="1543"/>
|
<Caret Line="1581" Column="39" TopLine="1543"/>
|
||||||
</Position28>
|
</Position11>
|
||||||
<Position29>
|
<Position12>
|
||||||
<Filename Value="..\..\xlsbiff2.pas"/>
|
<Filename Value="..\..\xlsbiff2.pas"/>
|
||||||
<Caret Line="1076" Column="29" TopLine="1066"/>
|
<Caret Line="1076" Column="29" TopLine="1066"/>
|
||||||
</Position29>
|
</Position12>
|
||||||
<Position30>
|
<Position13>
|
||||||
<Filename Value="..\..\fpspreadsheet.pas"/>
|
<Filename Value="..\..\fpspreadsheet.pas"/>
|
||||||
<Caret Line="618" Column="27" TopLine="580"/>
|
<Caret Line="618" Column="27" TopLine="580"/>
|
||||||
|
</Position13>
|
||||||
|
<Position14>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="253" Column="37" TopLine="245"/>
|
||||||
|
</Position14>
|
||||||
|
<Position15>
|
||||||
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
|
<Caret Line="758" Column="1" TopLine="748"/>
|
||||||
|
</Position15>
|
||||||
|
<Position16>
|
||||||
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
|
<Caret Line="765" Column="47" TopLine="762"/>
|
||||||
|
</Position16>
|
||||||
|
<Position17>
|
||||||
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
|
<Caret Line="351" Column="75" TopLine="329"/>
|
||||||
|
</Position17>
|
||||||
|
<Position18>
|
||||||
|
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||||
|
<Caret Line="94" Column="1" TopLine="72"/>
|
||||||
|
</Position18>
|
||||||
|
<Position19>
|
||||||
|
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||||
|
<Caret Line="1546" Column="31" TopLine="1525"/>
|
||||||
|
</Position19>
|
||||||
|
<Position20>
|
||||||
|
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||||
|
<Caret Line="1573" Column="37" TopLine="1552"/>
|
||||||
|
</Position20>
|
||||||
|
<Position21>
|
||||||
|
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||||
|
<Caret Line="1634" Column="38" TopLine="1602"/>
|
||||||
|
</Position21>
|
||||||
|
<Position22>
|
||||||
|
<Filename Value="..\..\xlsbiff5.pas"/>
|
||||||
|
<Caret Line="1813" Column="3" TopLine="1794"/>
|
||||||
|
</Position22>
|
||||||
|
<Position23>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="98" Column="1" TopLine="81"/>
|
||||||
|
</Position23>
|
||||||
|
<Position24>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="1749" Column="3" TopLine="1737"/>
|
||||||
|
</Position24>
|
||||||
|
<Position25>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="1892" Column="3" TopLine="1874"/>
|
||||||
|
</Position25>
|
||||||
|
<Position26>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="1903" Column="3" TopLine="1892"/>
|
||||||
|
</Position26>
|
||||||
|
<Position27>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="1949" Column="3" TopLine="1933"/>
|
||||||
|
</Position27>
|
||||||
|
<Position28>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="1974" Column="3" TopLine="1956"/>
|
||||||
|
</Position28>
|
||||||
|
<Position29>
|
||||||
|
<Filename Value="..\..\xlsbiff8.pas"/>
|
||||||
|
<Caret Line="2068" Column="35" TopLine="2048"/>
|
||||||
|
</Position29>
|
||||||
|
<Position30>
|
||||||
|
<Filename Value="..\..\xlscommon.pas"/>
|
||||||
|
<Caret Line="328" Column="70" TopLine="308"/>
|
||||||
</Position30>
|
</Position30>
|
||||||
</JumpHistory>
|
</JumpHistory>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
|
@@ -86,11 +86,11 @@ type
|
|||||||
{ Record writing methods }
|
{ Record writing methods }
|
||||||
procedure ReadBlank(AStream: TStream); override;
|
procedure ReadBlank(AStream: TStream); override;
|
||||||
procedure ReadFont(const AStream: TStream);
|
procedure ReadFont(const AStream: TStream);
|
||||||
|
procedure ReadFormat(AStream: TStream); override;
|
||||||
procedure ReadFormula(AStream: TStream); override;
|
procedure ReadFormula(AStream: TStream); override;
|
||||||
procedure ReadFormulaExcel(AStream: TStream);
|
procedure ReadFormulaExcel(AStream: TStream);
|
||||||
procedure ReadLabel(AStream: TStream); override;
|
procedure ReadLabel(AStream: TStream); override;
|
||||||
procedure ReadMulRKValues(AStream: TStream);
|
procedure ReadMulRKValues(AStream: TStream);
|
||||||
procedure ReadNumber(AStream: TStream); override;
|
|
||||||
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
|
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
|
||||||
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
|
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
|
||||||
procedure ReadBoundsheet(AStream: TStream);
|
procedure ReadBoundsheet(AStream: TStream);
|
||||||
@@ -115,8 +115,6 @@ type
|
|||||||
ACell: PCell); override;
|
ACell: PCell); override;
|
||||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||||
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
||||||
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
|
||||||
const AValue: TDateTime; ACell: PCell); override;
|
|
||||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteEOF(AStream: TStream);
|
procedure WriteEOF(AStream: TStream);
|
||||||
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
||||||
@@ -231,6 +229,7 @@ const
|
|||||||
INT_EXCEL_ID_EOF = $000A;
|
INT_EXCEL_ID_EOF = $000A;
|
||||||
INT_EXCEL_ID_DIMENSIONS = $0200;
|
INT_EXCEL_ID_DIMENSIONS = $0200;
|
||||||
INT_EXCEL_ID_FONT = $0031;
|
INT_EXCEL_ID_FONT = $0031;
|
||||||
|
INT_EXCEL_ID_FORMAT = $041E;
|
||||||
INT_EXCEL_ID_FORMULA = $0006;
|
INT_EXCEL_ID_FORMULA = $0006;
|
||||||
INT_EXCEL_ID_INDEX = $020B;
|
INT_EXCEL_ID_INDEX = $020B;
|
||||||
INT_EXCEL_ID_LABEL = $0204;
|
INT_EXCEL_ID_LABEL = $0204;
|
||||||
@@ -969,7 +968,7 @@ begin
|
|||||||
{ IEE 754 floating-point value }
|
{ IEE 754 floating-point value }
|
||||||
AStream.WriteBuffer(AValue, 8);
|
AStream.WriteBuffer(AValue, 8);
|
||||||
end;
|
end;
|
||||||
|
(*
|
||||||
{*******************************************************************
|
{*******************************************************************
|
||||||
* TsSpreadBIFF2Writer.WriteDateTime ()
|
* TsSpreadBIFF2Writer.WriteDateTime ()
|
||||||
*
|
*
|
||||||
@@ -985,6 +984,7 @@ procedure TsSpreadBIFF5Writer.WriteDateTime(AStream: TStream;
|
|||||||
begin
|
begin
|
||||||
WriteLabel(AStream, ARow, ACol, FormatDateTime(ISO8601Format, AValue), ACell);
|
WriteLabel(AStream, ARow, ACol, FormatDateTime(ISO8601Format, AValue), ACell);
|
||||||
end;
|
end;
|
||||||
|
*)
|
||||||
|
|
||||||
{*******************************************************************
|
{*******************************************************************
|
||||||
* TsSpreadBIFF5Writer.WriteStyle ()
|
* TsSpreadBIFF5Writer.WriteStyle ()
|
||||||
@@ -1211,7 +1211,7 @@ begin
|
|||||||
lHorAlign := FFormattingStyles[i].HorAlignment;
|
lHorAlign := FFormattingStyles[i].HorAlignment;
|
||||||
lVertAlign := FFormattingStyles[i].VertAlignment;
|
lVertAlign := FFormattingStyles[i].VertAlignment;
|
||||||
lBackgroundColor := FFormattingStyles[i].BackgroundColor;
|
lBackgroundColor := FFormattingStyles[i].BackgroundColor;
|
||||||
(*
|
|
||||||
// Now apply the modifications.
|
// Now apply the modifications.
|
||||||
if uffNumberFormat in FFormattingStyles[i].UsedFormattingFields then
|
if uffNumberFormat in FFormattingStyles[i].UsedFormattingFields then
|
||||||
case FFormattingStyles[i].NumberFormat of
|
case FFormattingStyles[i].NumberFormat of
|
||||||
@@ -1271,7 +1271,6 @@ begin
|
|||||||
nfTimeInterval:
|
nfTimeInterval:
|
||||||
lFormatIndex := FORMAT_TIME_INTERVAL;
|
lFormatIndex := FORMAT_TIME_INTERVAL;
|
||||||
end;
|
end;
|
||||||
*)
|
|
||||||
|
|
||||||
if uffBorder in FFormattingStyles[i].UsedFormattingFields then
|
if uffBorder in FFormattingStyles[i].UsedFormattingFields then
|
||||||
lBorders := FFormattingStyles[i].Border;
|
lBorders := FFormattingStyles[i].Border;
|
||||||
@@ -1418,6 +1417,7 @@ begin
|
|||||||
INT_EXCEL_ID_BOF : ;
|
INT_EXCEL_ID_BOF : ;
|
||||||
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
|
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
|
||||||
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
INT_EXCEL_ID_FONT : ReadFont(AStream);
|
||||||
|
INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
|
||||||
INT_EXCEL_ID_XF : ReadXF(AStream);
|
INT_EXCEL_ID_XF : ReadXF(AStream);
|
||||||
INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
|
INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
|
||||||
INT_EXCEL_ID_EOF : SectionEOF := True;
|
INT_EXCEL_ID_EOF : SectionEOF := True;
|
||||||
@@ -1539,10 +1539,11 @@ procedure TsSpreadBIFF5Reader.ReadRichString(AStream: TStream);
|
|||||||
var
|
var
|
||||||
L: Word;
|
L: Word;
|
||||||
B: BYTE;
|
B: BYTE;
|
||||||
ARow, ACol, XF: Word;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: Word;
|
||||||
AStrValue: ansistring;
|
AStrValue: ansistring;
|
||||||
begin
|
begin
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
{ Byte String with 16-bit size }
|
{ Byte String with 16-bit size }
|
||||||
L := WordLEtoN(AStream.ReadWord());
|
L := WordLEtoN(AStream.ReadWord());
|
||||||
@@ -1565,10 +1566,11 @@ end;
|
|||||||
procedure TsSpreadBIFF5Reader.ReadRKValue(AStream: TStream);
|
procedure TsSpreadBIFF5Reader.ReadRKValue(AStream: TStream);
|
||||||
var
|
var
|
||||||
L: DWORD;
|
L: DWORD;
|
||||||
ARow, ACol, XF: WORD;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
Number: Double;
|
Number: Double;
|
||||||
begin
|
begin
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
{Encoded RK value}
|
{Encoded RK value}
|
||||||
L:=DWordLEtoN(AStream.ReadDWord);
|
L:=DWordLEtoN(AStream.ReadDWord);
|
||||||
@@ -1611,13 +1613,14 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadBIFF5Reader.ReadFormulaExcel(AStream: TStream);
|
procedure TsSpreadBIFF5Reader.ReadFormulaExcel(AStream: TStream);
|
||||||
var
|
var
|
||||||
ARow, ACol, XF: WORD;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
ResultFormula: Double;
|
ResultFormula: Double;
|
||||||
Data: array [0..7] of BYTE;
|
Data: array [0..7] of BYTE;
|
||||||
Flags: WORD;
|
Flags: WORD;
|
||||||
FormulaSize: BYTE;
|
FormulaSize: BYTE;
|
||||||
begin
|
begin
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
AStream.ReadBuffer(Data,Sizeof(Data));
|
AStream.ReadBuffer(Data,Sizeof(Data));
|
||||||
Flags:=WordLEtoN(AStream.ReadWord);
|
Flags:=WordLEtoN(AStream.ReadWord);
|
||||||
@@ -1628,7 +1631,7 @@ begin
|
|||||||
|
|
||||||
if SizeOf(Double)<>8 then Raise Exception.Create('Double is not 8 bytes');
|
if SizeOf(Double)<>8 then Raise Exception.Create('Double is not 8 bytes');
|
||||||
Move(Data[0],ResultFormula,sizeof(Data));
|
Move(Data[0],ResultFormula,sizeof(Data));
|
||||||
FWorksheet.WriteNumber(ARow,ACol,ResultFormula);
|
FWorksheet.WriteNumber(ARow, ACol, ResultFormula);
|
||||||
|
|
||||||
{ Add attributes to cell }
|
{ Add attributes to cell }
|
||||||
ApplyCellFormatting(ARow, ACol, XF);
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
@@ -1805,7 +1808,8 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadBIFF5Reader.ReadBlank(AStream: TStream);
|
procedure TsSpreadBIFF5Reader.ReadBlank(AStream: TStream);
|
||||||
var
|
var
|
||||||
ARow, ACol, XF: Word;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: Word;
|
||||||
begin
|
begin
|
||||||
{ Read row, column, and XF index from BIFF file }
|
{ Read row, column, and XF index from BIFF file }
|
||||||
ReadRowColXF(AStream, ARow, ACol, XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
@@ -1875,6 +1879,34 @@ begin
|
|||||||
FWorkbook.AddFont(font);
|
FWorkbook.AddFont(font);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Read the FORMAT record for formatting numerical data
|
||||||
|
procedure TsSpreadBIFF5Reader.ReadFormat(AStream: TStream);
|
||||||
|
var
|
||||||
|
lData: TFormatListData;
|
||||||
|
str: AnsiString;
|
||||||
|
len: byte;
|
||||||
|
begin
|
||||||
|
lData := TFormatListData.Create;
|
||||||
|
|
||||||
|
// Record FORMAT, BIFF 8 (5.49):
|
||||||
|
// Offset Size Contents
|
||||||
|
// 0 2 Format index used in other records
|
||||||
|
// 2 var Number format string (byte string, 8-bit string length)
|
||||||
|
// From BIFF5 on: indexes 0..163 are built in
|
||||||
|
|
||||||
|
// format index
|
||||||
|
lData.Index := WordLEtoN(AStream.ReadWord);
|
||||||
|
|
||||||
|
// number format string
|
||||||
|
len := AStream.ReadByte;
|
||||||
|
SetLength(str, len);
|
||||||
|
AStream.ReadBuffer(str[1], len);
|
||||||
|
lData.FormatString := str;
|
||||||
|
|
||||||
|
// Add to the list
|
||||||
|
FFormatList.Add(lData);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF5Reader.ReadFormula(AStream: TStream);
|
procedure TsSpreadBIFF5Reader.ReadFormula(AStream: TStream);
|
||||||
begin
|
begin
|
||||||
|
|
||||||
@@ -1883,7 +1915,8 @@ end;
|
|||||||
procedure TsSpreadBIFF5Reader.ReadLabel(AStream: TStream);
|
procedure TsSpreadBIFF5Reader.ReadLabel(AStream: TStream);
|
||||||
var
|
var
|
||||||
L: Word;
|
L: Word;
|
||||||
ARow, ACol, XF: WORD;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
AValue: array[0..255] of Char;
|
AValue: array[0..255] of Char;
|
||||||
AStrValue: ansistring;
|
AStrValue: ansistring;
|
||||||
begin
|
begin
|
||||||
@@ -1902,23 +1935,6 @@ begin
|
|||||||
ApplyCellFormatting(ARow, ACol, XF);
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF5Reader.ReadNumber(AStream: TStream);
|
|
||||||
var
|
|
||||||
ARow, ACol, XF: WORD;
|
|
||||||
AValue: Double;
|
|
||||||
begin
|
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
|
||||||
|
|
||||||
{ IEE 754 floating-point value }
|
|
||||||
AStream.ReadBuffer(AValue, 8);
|
|
||||||
|
|
||||||
{ Save the data }
|
|
||||||
FWorksheet.WriteNumber(ARow, ACol, AValue);
|
|
||||||
|
|
||||||
{ Add attributes to cell }
|
|
||||||
ApplyCellFormatting(ARow, ACol, XF);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
|
|
||||||
|
@@ -63,11 +63,6 @@ uses
|
|||||||
fpsutils, lazutf8;
|
fpsutils, lazutf8;
|
||||||
|
|
||||||
type
|
type
|
||||||
TFormatRecordData = class
|
|
||||||
public
|
|
||||||
Index: Integer;
|
|
||||||
FormatString: widestring;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TsSpreadBIFF8Reader }
|
{ TsSpreadBIFF8Reader }
|
||||||
|
|
||||||
@@ -78,46 +73,30 @@ type
|
|||||||
FWorksheetNames: TStringList;
|
FWorksheetNames: TStringList;
|
||||||
FCurrentWorksheet: Integer;
|
FCurrentWorksheet: Integer;
|
||||||
FSharedStringTable: TStringList;
|
FSharedStringTable: TStringList;
|
||||||
FFormatList: TFPList; // of TFormatRecordData
|
|
||||||
function DecodeRKValue(const ARK: DWORD): Double;
|
function DecodeRKValue(const ARK: DWORD): Double;
|
||||||
// procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Integer);
|
|
||||||
procedure ExtractNumberFormat(AXFIndex: WORD;
|
|
||||||
out ANumberFormat: TsNumberFormat; out ADecimals: Word;
|
|
||||||
out ANumberFormatStr: String);
|
|
||||||
// Tries to find if a number cell is actually a date/datetime/time cell
|
|
||||||
// and retrieve the value
|
|
||||||
function IsDateTime(Number: Double; ANumberFormat: TsNumberFormat; var ADateTime: TDateTime): Boolean;
|
|
||||||
function ReadWideString(const AStream: TStream; const ALength: WORD): WideString; overload;
|
function ReadWideString(const AStream: TStream; const ALength: WORD): WideString; overload;
|
||||||
function ReadWideString(const AStream: TStream; const AUse8BitLength: Boolean): WideString; overload;
|
function ReadWideString(const AStream: TStream; const AUse8BitLength: Boolean): WideString; overload;
|
||||||
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
|
procedure ReadWorkbookGlobals(AStream: TStream; AData: TsWorkbook);
|
||||||
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
|
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
|
||||||
procedure ReadBoundsheet(AStream: TStream);
|
procedure ReadBoundsheet(AStream: TStream);
|
||||||
|
|
||||||
procedure ReadRKValue(const AStream: TStream);
|
procedure ReadRKValue(const AStream: TStream);
|
||||||
procedure ReadMulRKValues(const AStream: TStream);
|
procedure ReadMulRKValues(const AStream: TStream);
|
||||||
// procedure ReadRowColXF(const AStream: TStream; out ARow,ACol,AXF: WORD);
|
|
||||||
function ReadString(const AStream: TStream; const ALength: WORD): UTF8String;
|
function ReadString(const AStream: TStream; const ALength: WORD): UTF8String;
|
||||||
procedure ReadSST(const AStream: TStream);
|
procedure ReadSST(const AStream: TStream);
|
||||||
procedure ReadLabelSST(const AStream: TStream);
|
procedure ReadLabelSST(const AStream: TStream);
|
||||||
// Read XF record
|
// Read XF record
|
||||||
procedure ReadXF(const AStream: TStream);
|
procedure ReadXF(const AStream: TStream);
|
||||||
// Read FORMAT record (cell formatting)
|
|
||||||
procedure ReadFormat(const AStream: TStream);
|
|
||||||
// Finds format record for XF record pointed to by cell
|
|
||||||
// Will not return info for built-in formats
|
|
||||||
function FindFormatRecordForCell(const AXFIndex: Integer): TFormatRecordData;
|
|
||||||
// Workbook Globals records
|
// Workbook Globals records
|
||||||
// procedure ReadCodepage in xlscommon
|
// procedure ReadCodepage in xlscommon
|
||||||
// procedure ReadDateMode in xlscommon
|
// procedure ReadDateMode in xlscommon
|
||||||
procedure ReadFont(const AStream: TStream);
|
procedure ReadFont(const AStream: TStream);
|
||||||
|
procedure ReadFormat(AStream: TStream); override;
|
||||||
{ Record reading methods }
|
{ Record reading methods }
|
||||||
procedure ReadBlank(AStream: TStream); override;
|
procedure ReadBlank(AStream: TStream); override;
|
||||||
procedure ReadFormula(AStream: TStream); override;
|
procedure ReadFormula(AStream: TStream); override;
|
||||||
procedure ReadLabel(AStream: TStream); override;
|
procedure ReadLabel(AStream: TStream); override;
|
||||||
procedure ReadNumber(AStream: TStream); override;
|
|
||||||
procedure ReadRichString(const AStream: TStream);
|
procedure ReadRichString(const AStream: TStream);
|
||||||
public
|
public
|
||||||
constructor Create(AWorkbook: TsWorkbook); override;
|
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
{ General reading methods }
|
{ General reading methods }
|
||||||
procedure ReadFromFile(AFileName: string; AData: TsWorkbook); override;
|
procedure ReadFromFile(AFileName: string; AData: TsWorkbook); override;
|
||||||
@@ -138,8 +117,8 @@ type
|
|||||||
ACell: PCell); override;
|
ACell: PCell); override;
|
||||||
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
procedure WriteBOF(AStream: TStream; ADataType: Word);
|
||||||
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
|
||||||
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
// procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
const AValue: TDateTime; ACell: PCell); override;
|
// const AValue: TDateTime; ACell: PCell); override;
|
||||||
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
|
||||||
procedure WriteEOF(AStream: TStream);
|
procedure WriteEOF(AStream: TStream);
|
||||||
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
procedure WriteFont(AStream: TStream; AFont: TsFont);
|
||||||
@@ -716,24 +695,6 @@ begin
|
|||||||
AStream.WriteBuffer(WideStringToLE(WideSheetName)[1], Len * Sizeof(WideChar));
|
AStream.WriteBuffer(WideStringToLE(WideSheetName)[1], Len * Sizeof(WideChar));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{*******************************************************************
|
|
||||||
* TsSpreadBIFF8Writer.WriteDateTime ()
|
|
||||||
*
|
|
||||||
* DESCRIPTION: Writes a date/time/datetime to an
|
|
||||||
* Excel 8 NUMBER record, with a date/time format
|
|
||||||
* (There is no separate date record type in xls)
|
|
||||||
*******************************************************************}
|
|
||||||
procedure TsSpreadBIFF8Writer.WriteDateTime(AStream: TStream; const ARow,
|
|
||||||
ACol: Cardinal; const AValue: TDateTime; ACell: PCell);
|
|
||||||
var
|
|
||||||
ExcelDateSerial: double;
|
|
||||||
begin
|
|
||||||
ExcelDateSerial:=ConvertDateTimeToExcelDateTime(AValue,FDateMode);
|
|
||||||
// fpspreadsheet must already have set formatting to a date/datetime format, so
|
|
||||||
// this will get written out as a pointer to the relevant XF record.
|
|
||||||
// In the end, dates in xls are just numbers with a format. Pass it on to WriteNumber:
|
|
||||||
WriteNumber(AStream,ARow,ACol,ExcelDateSerial,ACell);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Writes an Excel 8 DIMENSIONS record
|
Writes an Excel 8 DIMENSIONS record
|
||||||
@@ -1522,18 +1483,8 @@ end;
|
|||||||
|
|
||||||
{ TsSpreadBIFF8Reader }
|
{ TsSpreadBIFF8Reader }
|
||||||
|
|
||||||
constructor TsSpreadBIFF8Reader.Create(AWorkbook: TsWorkbook);
|
|
||||||
begin
|
|
||||||
inherited Create(AWorkbook);
|
|
||||||
FFormatList := TFPList.Create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TsSpreadBIFF8Reader.Destroy;
|
destructor TsSpreadBIFF8Reader.Destroy;
|
||||||
var
|
|
||||||
j: integer;
|
|
||||||
begin
|
begin
|
||||||
for j := FFormatList.Count-1 downto 0 do TObject(FFormatList[j]).Free;
|
|
||||||
FFormatList.Free;
|
|
||||||
if Assigned(FSharedStringTable) then FSharedStringTable.Free;
|
if Assigned(FSharedStringTable) then FSharedStringTable.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
@@ -1567,129 +1518,6 @@ begin
|
|||||||
Result:=Number;
|
Result:=Number;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ExtractNumberFormat(AXFIndex: WORD;
|
|
||||||
out ANumberFormat: TsNumberFormat; out ADecimals: Word;
|
|
||||||
out ANumberFormatStr: String);
|
|
||||||
const
|
|
||||||
{ see ➜ 5.49 }
|
|
||||||
NOT_USED = nfGeneral;
|
|
||||||
fmts: array[1..58] of TsNumberFormat = (
|
|
||||||
nfFixed, nfFixed, nfFixedTh, nfFixedTh, nfFixedTh, // 1..5
|
|
||||||
nfFixedTh, nfFixedTh, nfFixedTh, nfPercentage, nfPercentage, // 6..10
|
|
||||||
nfExp, NOT_USED, NOT_USED, nfShortDate, nfShortDate, // 11..15
|
|
||||||
nfFmtDateTime, nfFmtDateTime, nfShortTimeAM, nfLongTimeAM, nfShortTime, // 16..20
|
|
||||||
nfLongTime, nfShortDateTime, NOT_USED, NOT_USED, NOT_USED, // 21..25
|
|
||||||
NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, // 26..30
|
|
||||||
NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, // 31..35
|
|
||||||
NOT_USED, nfFixedTh, nfFixedTh, nfFixedTh, nfFixedTh, // 36..40
|
|
||||||
nfFixedTh, nfFixedTh, nfFixedTh, nfFixedTh, nfFmtDateTime, // 41..45
|
|
||||||
nfTimeInterval, nfFmtDateTime, nfSci, NOT_USED, NOT_USED, // 46..50
|
|
||||||
NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, // 51..55
|
|
||||||
NOT_USED, NOT_USED, NOT_USED // 56..58
|
|
||||||
);
|
|
||||||
decs: array[1..58] of word = (
|
|
||||||
0, 2, 0, 2, 0, 0, 2, 2, 0, 2, // 1..10
|
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11..20
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21..30
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 2, 2, // 31..40
|
|
||||||
0, 0, 2, 2, 0, 3, 0, 1, 0, 0, // 41..50 #48 is "scientific", use "exponential" instead
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0); // 51..58
|
|
||||||
var
|
|
||||||
lFormatData: TFormatRecordData;
|
|
||||||
lXFData: TXFListData;
|
|
||||||
isAMPM: Boolean;
|
|
||||||
isLongTime: Boolean;
|
|
||||||
isMilliSec: Boolean;
|
|
||||||
t,d: Boolean;
|
|
||||||
begin
|
|
||||||
ANumberFormat := nfGeneral;
|
|
||||||
ANumberFormatStr := '';
|
|
||||||
ADecimals := 0;
|
|
||||||
|
|
||||||
lFormatData := FindFormatRecordForCell(AXFIndex);
|
|
||||||
{Record FORMAT, BIFF8 (5.49):
|
|
||||||
Offset Size Contents
|
|
||||||
0 2 Format index used in other records
|
|
||||||
}
|
|
||||||
|
|
||||||
if lFormatData = nil then begin
|
|
||||||
// no custom format, so first test for default formats
|
|
||||||
lXFData := TXFListData (FXFList.Items[AXFIndex]);
|
|
||||||
case lXFData.FormatIndex of
|
|
||||||
FORMAT_DATE_DM:
|
|
||||||
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'DM'; end;
|
|
||||||
FORMAT_DATE_MY:
|
|
||||||
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'MY'; end;
|
|
||||||
FORMAT_TIME_MS:
|
|
||||||
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'MS'; end;
|
|
||||||
FORMAT_TIME_MSZ:
|
|
||||||
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'MSZ'; end;
|
|
||||||
else
|
|
||||||
if (lXFData.FormatIndex > 0) and (lXFData.FormatIndex <= 58) then begin
|
|
||||||
ANumberFormat := fmts[lXFData.FormatIndex];
|
|
||||||
ADecimals := decs[lXFData.FormatIndex];
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end else
|
|
||||||
// Check custom formats if they have / in format string (this can fail for
|
|
||||||
// custom text formats)
|
|
||||||
if IsPercentNumberFormat(lFormatData.FormatString, ADecimals) then
|
|
||||||
ANumberFormat := nfPercentage
|
|
||||||
else
|
|
||||||
if IsExpNumberFormat(lFormatData.Formatstring, ADecimals) then
|
|
||||||
ANumberFormat := nfExp
|
|
||||||
else
|
|
||||||
if IsThousandSepNumberFormat(lFormatData.FormatString, ADecimals) then
|
|
||||||
ANumberFormat := nfFixedTh
|
|
||||||
else
|
|
||||||
if IsFixedNumberFormat(lFormatData.FormatString, ADecimals) then
|
|
||||||
ANumberFormat := nfFixed
|
|
||||||
else begin
|
|
||||||
t := IsTimeFormat(lFormatData.FormatString, isLongTime, isAMPM, isMilliSec);
|
|
||||||
d := IsDateFormat(lFormatData.FormatString);
|
|
||||||
if d and t then
|
|
||||||
ANumberFormat := nfShortDateTime
|
|
||||||
else
|
|
||||||
if d then
|
|
||||||
ANumberFormat := nfShortDate
|
|
||||||
else
|
|
||||||
if t then begin
|
|
||||||
if isAMPM then begin
|
|
||||||
if isLongTime then
|
|
||||||
ANumberFormat := nfLongTimeAM
|
|
||||||
else
|
|
||||||
ANumberFormat := nfShortTimeAM;
|
|
||||||
end else begin
|
|
||||||
if isLongTime then
|
|
||||||
ANumberFormat := nfLongTime
|
|
||||||
else
|
|
||||||
ANumberFormat := nfShortTime;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TsSpreadBIFF8Reader.IsDateTime(Number: Double;
|
|
||||||
ANumberFormat: TsNumberFormat; var ADateTime: TDateTime): boolean;
|
|
||||||
// Convert the number to a date/time and return that if it is
|
|
||||||
begin
|
|
||||||
if ANumberFormat in [
|
|
||||||
nfShortDateTime, nfFmtDateTime, nfShortDate,
|
|
||||||
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM] then
|
|
||||||
begin
|
|
||||||
ADateTime := ConvertExcelDateTimeToDateTime(Number, FDateMode);
|
|
||||||
Result := true;
|
|
||||||
end else
|
|
||||||
if ANumberFormat = nfTimeInterval then begin
|
|
||||||
ADateTime := Number;
|
|
||||||
Result := true;
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
ADateTime := 0;
|
|
||||||
Result := false;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TsSpreadBIFF8Reader.ReadWideString(const AStream: TStream;
|
function TsSpreadBIFF8Reader.ReadWideString(const AStream: TStream;
|
||||||
const ALength: WORD): WideString;
|
const ALength: WORD): WideString;
|
||||||
var
|
var
|
||||||
@@ -1917,7 +1745,8 @@ end;
|
|||||||
procedure TsSpreadBIFF8Reader.ReadRKValue(const AStream: TStream);
|
procedure TsSpreadBIFF8Reader.ReadRKValue(const AStream: TStream);
|
||||||
var
|
var
|
||||||
RK: DWORD;
|
RK: DWORD;
|
||||||
ARow, ACol, XF: WORD;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
lDateTime: TDateTime;
|
lDateTime: TDateTime;
|
||||||
Number: Double;
|
Number: Double;
|
||||||
nf: TsNumberFormat; // Number format
|
nf: TsNumberFormat; // Number format
|
||||||
@@ -1925,7 +1754,7 @@ var
|
|||||||
nfs: String; // Number format string
|
nfs: String; // Number format string
|
||||||
begin
|
begin
|
||||||
{Retrieve XF record, row and column}
|
{Retrieve XF record, row and column}
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
{Encoded RK value}
|
{Encoded RK value}
|
||||||
RK:=DWordLEtoN(AStream.ReadDWord);
|
RK:=DWordLEtoN(AStream.ReadDWord);
|
||||||
@@ -2059,7 +1888,8 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadBlank(AStream: TStream);
|
procedure TsSpreadBIFF8Reader.ReadBlank(AStream: TStream);
|
||||||
var
|
var
|
||||||
ARow, ACol, XF: Word;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: Word;
|
||||||
begin
|
begin
|
||||||
{ Read row, column, and XF index from BIFF file }
|
{ Read row, column, and XF index from BIFF file }
|
||||||
ReadRowColXF(AStream, ARow, ACol, XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
@@ -2069,7 +1899,8 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadFormula(AStream: TStream);
|
procedure TsSpreadBIFF8Reader.ReadFormula(AStream: TStream);
|
||||||
var
|
var
|
||||||
ARow, ACol, XF: WORD;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
ResultFormula: Double;
|
ResultFormula: Double;
|
||||||
Data: array [0..7] of BYTE;
|
Data: array [0..7] of BYTE;
|
||||||
Flags: WORD;
|
Flags: WORD;
|
||||||
@@ -2079,7 +1910,7 @@ begin
|
|||||||
{ BIFF Record header }
|
{ BIFF Record header }
|
||||||
{ BIFF Record data }
|
{ BIFF Record data }
|
||||||
{ Index to XF Record }
|
{ Index to XF Record }
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
{ Result of the formula in IEE 754 floating-point value }
|
{ Result of the formula in IEE 754 floating-point value }
|
||||||
AStream.ReadBuffer(Data,Sizeof(Data));
|
AStream.ReadBuffer(Data,Sizeof(Data));
|
||||||
@@ -2114,12 +1945,13 @@ procedure TsSpreadBIFF8Reader.ReadLabel(AStream: TStream);
|
|||||||
var
|
var
|
||||||
L: Word;
|
L: Word;
|
||||||
StringFlags: BYTE;
|
StringFlags: BYTE;
|
||||||
ARow, ACol, XF: Word;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: Word;
|
||||||
WideStrValue: WideString;
|
WideStrValue: WideString;
|
||||||
AnsiStrValue: AnsiString;
|
AnsiStrValue: AnsiString;
|
||||||
begin
|
begin
|
||||||
{ BIFF Record data: Row, Column, XF Index }
|
{ BIFF Record data: Row, Column, XF Index }
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
{ Byte String with 16-bit size }
|
{ Byte String with 16-bit size }
|
||||||
L := WordLEtoN(AStream.ReadWord());
|
L := WordLEtoN(AStream.ReadWord());
|
||||||
@@ -2134,42 +1966,15 @@ begin
|
|||||||
ApplyCellFormatting(ARow, ACol, XF);
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadNumber(AStream: TStream);
|
|
||||||
// Tries to read number from stream and write result to worksheet.
|
|
||||||
// Needs to check if a number is actually a date format
|
|
||||||
var
|
|
||||||
ARow, ACol, XF: Word;
|
|
||||||
AValue: Double;
|
|
||||||
lDateTime: TDateTime;
|
|
||||||
nf: TsNumberFormat;
|
|
||||||
nd: word;
|
|
||||||
nfs: String;
|
|
||||||
begin
|
|
||||||
{Retrieve XF record, row and column}
|
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
|
||||||
|
|
||||||
{ IEE 754 floating-point value }
|
|
||||||
AStream.ReadBuffer(AValue, 8);
|
|
||||||
|
|
||||||
{Find out what cell type, set contenttype and value}
|
|
||||||
ExtractNumberFormat(XF, nf, nd, nfs);
|
|
||||||
if IsDateTime(AValue, nf, lDateTime) then
|
|
||||||
FWorksheet.WriteDateTime(ARow, ACol, lDateTime, nf, nfs)
|
|
||||||
else
|
|
||||||
FWorksheet.WriteNumber(ARow,ACol,AValue,nf,nd);
|
|
||||||
|
|
||||||
{Add attributes}
|
|
||||||
ApplyCellFormatting(ARow, ACol, XF);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadRichString(const AStream: TStream);
|
procedure TsSpreadBIFF8Reader.ReadRichString(const AStream: TStream);
|
||||||
var
|
var
|
||||||
L: Word;
|
L: Word;
|
||||||
B: WORD;
|
B: WORD;
|
||||||
ARow, ACol, XF: Word;
|
ARow, ACol: Cardinal;
|
||||||
|
XF: Word;
|
||||||
AStrValue: ansistring;
|
AStrValue: ansistring;
|
||||||
begin
|
begin
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
|
|
||||||
{ Byte String with 16-bit size }
|
{ Byte String with 16-bit size }
|
||||||
L := WordLEtoN(AStream.ReadWord());
|
L := WordLEtoN(AStream.ReadWord());
|
||||||
@@ -2257,12 +2062,13 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadLabelSST(const AStream: TStream);
|
procedure TsSpreadBIFF8Reader.ReadLabelSST(const AStream: TStream);
|
||||||
var
|
var
|
||||||
ACol,ARow,XF: WORD;
|
ACol,ARow: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
SSTIndex: DWORD;
|
SSTIndex: DWORD;
|
||||||
begin
|
begin
|
||||||
ReadRowColXF(AStream,ARow,ACol,XF);
|
ReadRowColXF(AStream, ARow, ACol, XF);
|
||||||
SSTIndex:=DWordLEtoN(AStream.ReadDWord);
|
SSTIndex := DWordLEtoN(AStream.ReadDWord);
|
||||||
if SizeInt(SSTIndex)>=FSharedStringTable.Count then begin
|
if SizeInt(SSTIndex) >= FSharedStringTable.Count then begin
|
||||||
Raise Exception.CreateFmt('Index %d in SST out of range (0-%d)',[Integer(SSTIndex),FSharedStringTable.Count-1]);
|
Raise Exception.CreateFmt('Index %d in SST out of range (0-%d)',[Integer(SSTIndex),FSharedStringTable.Count-1]);
|
||||||
end;
|
end;
|
||||||
FWorksheet.WriteUTF8Text(ARow, ACol, FSharedStringTable[SSTIndex]);
|
FWorksheet.WriteUTF8Text(ARow, ACol, FSharedStringTable[SSTIndex]);
|
||||||
@@ -2347,41 +2153,6 @@ begin
|
|||||||
FXFList.Add(lData);
|
FXFList.Add(lData);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadFormat(const AStream: TStream);
|
|
||||||
var
|
|
||||||
lData: TFormatRecordData;
|
|
||||||
begin
|
|
||||||
lData := TFormatRecordData.Create;
|
|
||||||
|
|
||||||
// Record FORMAT, BIFF8 (5.49):
|
|
||||||
// Offset Size Contents
|
|
||||||
// 0 2 Format index used in other records
|
|
||||||
// From BIFF5 on: indexes 0..163 are built in
|
|
||||||
lData.Index := WordLEtoN(AStream.ReadWord);
|
|
||||||
|
|
||||||
// 2 var. Number format string (Unicode string, 16-bit string length, ➜2.5.3)
|
|
||||||
lData.FormatString := ReadWideString(AStream, False);
|
|
||||||
|
|
||||||
// Add to the list
|
|
||||||
FFormatList.Add(lData);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TsSpreadBIFF8Reader.FindFormatRecordForCell(const AXFIndex: Integer
|
|
||||||
): TFormatRecordData;
|
|
||||||
var
|
|
||||||
lXFData: TXFListData;
|
|
||||||
lFormatData: TFormatRecordData;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
Result := nil;
|
|
||||||
lXFData := TXFListData(FXFList.Items[AXFIndex]);
|
|
||||||
for i := 0 to FFormatList.Count-1 do
|
|
||||||
begin
|
|
||||||
lFormatData := TFormatRecordData(FFormatList.Items[i]);
|
|
||||||
if lFormatData.Index = lXFData.FormatIndex then Exit(lFormatData);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TsSpreadBIFF8Reader.ReadFont(const AStream: TStream);
|
procedure TsSpreadBIFF8Reader.ReadFont(const AStream: TStream);
|
||||||
var
|
var
|
||||||
lCodePage: Word;
|
lCodePage: Word;
|
||||||
@@ -2442,6 +2213,27 @@ begin
|
|||||||
FWorkbook.AddFont(font);
|
FWorkbook.AddFont(font);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Read the FORMAT record for formatting numerical data
|
||||||
|
procedure TsSpreadBIFF8Reader.ReadFormat(AStream: TStream);
|
||||||
|
var
|
||||||
|
lData: TFormatListData;
|
||||||
|
begin
|
||||||
|
lData := TFormatListData.Create;
|
||||||
|
|
||||||
|
// Record FORMAT, BIFF 8 (5.49):
|
||||||
|
// Offset Size Contents
|
||||||
|
// 0 2 Format index used in other records
|
||||||
|
// 2 var Number format string (Unicode string, 16-bit string length)
|
||||||
|
// From BIFF5 on: indexes 0..163 are built in
|
||||||
|
lData.Index := WordLEtoN(AStream.ReadWord);
|
||||||
|
|
||||||
|
// 2 var. Number format string (Unicode string, 16-bit string length, ➜2.5.3)
|
||||||
|
lData.FormatString := ReadWideString(AStream, False);
|
||||||
|
|
||||||
|
// Add to the list
|
||||||
|
FFormatList.Add(lData);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{*******************************************************************
|
{*******************************************************************
|
||||||
* Initialization section
|
* Initialization section
|
||||||
|
@@ -310,24 +310,45 @@ type
|
|||||||
BackgroundColor: TsColor;
|
BackgroundColor: TsColor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Contents of the format record for BIFF5/8 }
|
||||||
|
TFormatListData = class
|
||||||
|
public
|
||||||
|
Index: Integer;
|
||||||
|
FormatString: widestring;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TsSpreadBIFFReader }
|
{ TsSpreadBIFFReader }
|
||||||
TsSpreadBIFFReader = class(TsCustomSpreadReader)
|
TsSpreadBIFFReader = class(TsCustomSpreadReader)
|
||||||
protected
|
protected
|
||||||
FCodepage: string; // in a format prepared for lconvencoding.ConvertEncoding
|
FCodepage: string; // in a format prepared for lconvencoding.ConvertEncoding
|
||||||
FDateMode: TDateMode;
|
FDateMode: TDateMode;
|
||||||
FPaletteFound: Boolean;
|
FPaletteFound: Boolean;
|
||||||
FXFList: TFPList;
|
FXFList: TFPList; // of TXFListData
|
||||||
procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Integer); virtual;
|
FFormatList: TFPList; // of TFormatListData
|
||||||
|
procedure ApplyCellFormatting(ARow, ACol: Cardinal; XFIndex: Word); virtual;
|
||||||
|
// Returns the numberformat for a given XF record
|
||||||
|
procedure ExtractNumberFormat(AXFIndex: WORD;
|
||||||
|
out ANumberFormat: TsNumberFormat; out ADecimals: Word;
|
||||||
|
out ANumberFormatStr: String);
|
||||||
|
// Finds format record for XF record pointed to by cell
|
||||||
|
// Will not return info for built-in formats
|
||||||
|
function FindFormatDataForCell(const AXFIndex: Integer): TFormatListData;
|
||||||
|
// Tries to find if a number cell is actually a date/datetime/time cell and retrieves the value
|
||||||
|
function IsDateTime(Number: Double; ANumberFormat: TsNumberFormat; var ADateTime: TDateTime): Boolean;
|
||||||
// Here we can add reading of records which didn't change across BIFF5-8 versions
|
// Here we can add reading of records which didn't change across BIFF5-8 versions
|
||||||
procedure ReadCodePage(AStream: TStream);
|
procedure ReadCodePage(AStream: TStream);
|
||||||
// Read column info
|
// Read column info
|
||||||
procedure ReadColInfo(const AStream: TStream);
|
procedure ReadColInfo(const AStream: TStream);
|
||||||
// Figures out what the base year for dates is for this file
|
// Figures out what the base year for dates is for this file
|
||||||
procedure ReadDateMode(AStream: TStream);
|
procedure ReadDateMode(AStream: TStream);
|
||||||
|
// Read FORMAT record (cell formatting)
|
||||||
|
procedure ReadFormat(AStream: TStream); virtual;
|
||||||
|
// Read floating point number
|
||||||
|
procedure ReadNumber(AStream: TStream); virtual;
|
||||||
// Read palette
|
// Read palette
|
||||||
procedure ReadPalette(AStream: TStream);
|
procedure ReadPalette(AStream: TStream);
|
||||||
// Read the row, column, and XF index at the current stream position
|
// Read the row, column, and XF index at the current stream position
|
||||||
procedure ReadRowColXF(AStream: TStream; out ARow, ACol, AXF: Word);
|
procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word);
|
||||||
// Read row info
|
// Read row info
|
||||||
procedure ReadRowInfo(AStream: TStream); virtual;
|
procedure ReadRowInfo(AStream: TStream); virtual;
|
||||||
public
|
public
|
||||||
@@ -355,6 +376,9 @@ type
|
|||||||
procedure WriteColInfos(AStream: TStream; ASheet: TsWorksheet);
|
procedure WriteColInfos(AStream: TStream; ASheet: TsWorksheet);
|
||||||
// Writes out DATEMODE record depending on FDateMode
|
// Writes out DATEMODE record depending on FDateMode
|
||||||
procedure WriteDateMode(AStream: TStream);
|
procedure WriteDateMode(AStream: TStream);
|
||||||
|
// Writes out a TIME/DATE/TIMETIME
|
||||||
|
procedure WriteDateTime(AStream: TStream; const ARow, ACol: Cardinal;
|
||||||
|
const AValue: TDateTime; ACell: PCell); override;
|
||||||
// Writes out a PALETTE record containing all colors defined in the workbook
|
// Writes out a PALETTE record containing all colors defined in the workbook
|
||||||
procedure WritePalette(AStream: TStream);
|
procedure WritePalette(AStream: TStream);
|
||||||
public
|
public
|
||||||
@@ -429,6 +453,7 @@ constructor TsSpreadBIFFReader.Create(AWorkbook: TsWorkbook);
|
|||||||
begin
|
begin
|
||||||
inherited Create(AWorkbook);
|
inherited Create(AWorkbook);
|
||||||
FXFList := TFPList.Create;
|
FXFList := TFPList.Create;
|
||||||
|
FFormatList := TFPList.Create;
|
||||||
// Initial base date in case it won't be read from file
|
// Initial base date in case it won't be read from file
|
||||||
FDateMode := dm1900;
|
FDateMode := dm1900;
|
||||||
end;
|
end;
|
||||||
@@ -439,12 +464,14 @@ var
|
|||||||
begin
|
begin
|
||||||
for j := FXFList.Count-1 downto 0 do TObject(FXFList[j]).Free;
|
for j := FXFList.Count-1 downto 0 do TObject(FXFList[j]).Free;
|
||||||
FXFList.Free;
|
FXFList.Free;
|
||||||
|
for j := FFormatList.Count-1 downto 0 do TObject(FFormatList[j]).Free;
|
||||||
|
FFormatList.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Applies the XF formatting given by the given index to the specified cell }
|
{ Applies the XF formatting given by the given index to the specified cell }
|
||||||
procedure TsSpreadBIFFReader.ApplyCellFormatting(ARow, ACol: Cardinal;
|
procedure TsSpreadBIFFReader.ApplyCellFormatting(ARow, ACol: Cardinal;
|
||||||
XFIndex: Integer);
|
XFIndex: Word);
|
||||||
var
|
var
|
||||||
lCell: PCell;
|
lCell: PCell;
|
||||||
XFData: TXFListData;
|
XFData: TXFListData;
|
||||||
@@ -493,6 +520,146 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadBIFFReader.ExtractNumberFormat(AXFIndex: WORD;
|
||||||
|
out ANumberFormat: TsNumberFormat; out ADecimals: Word;
|
||||||
|
out ANumberFormatStr: String);
|
||||||
|
const
|
||||||
|
{ see ➜ 5.49 }
|
||||||
|
NOT_USED = nfGeneral;
|
||||||
|
fmts: array[1..58] of TsNumberFormat = (
|
||||||
|
nfFixed, nfFixed, nfFixedTh, nfFixedTh, nfFixedTh, // 1..5
|
||||||
|
nfFixedTh, nfFixedTh, nfFixedTh, nfPercentage, nfPercentage, // 6..10
|
||||||
|
nfExp, NOT_USED, NOT_USED, nfShortDate, nfShortDate, // 11..15
|
||||||
|
nfFmtDateTime, nfFmtDateTime, nfShortTimeAM, nfLongTimeAM, nfShortTime, // 16..20
|
||||||
|
nfLongTime, nfShortDateTime, NOT_USED, NOT_USED, NOT_USED, // 21..25
|
||||||
|
NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, // 26..30
|
||||||
|
NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, // 31..35
|
||||||
|
NOT_USED, nfFixedTh, nfFixedTh, nfFixedTh, nfFixedTh, // 36..40
|
||||||
|
nfFixedTh, nfFixedTh, nfFixedTh, nfFixedTh, nfFmtDateTime, // 41..45
|
||||||
|
nfTimeInterval, nfFmtDateTime, nfSci, NOT_USED, NOT_USED, // 46..50
|
||||||
|
NOT_USED, NOT_USED, NOT_USED, NOT_USED, NOT_USED, // 51..55
|
||||||
|
NOT_USED, NOT_USED, NOT_USED // 56..58
|
||||||
|
);
|
||||||
|
decs: array[1..58] of word = (
|
||||||
|
0, 2, 0, 2, 0, 0, 2, 2, 0, 2, // 1..10
|
||||||
|
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 11..20
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21..30
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 2, 2, // 31..40
|
||||||
|
0, 0, 2, 2, 0, 3, 0, 1, 0, 0, // 41..50 #48 is "scientific", use "exponential" instead
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0); // 51..58
|
||||||
|
var
|
||||||
|
lFormatData: TFormatListData;
|
||||||
|
lXFData: TXFListData;
|
||||||
|
isAMPM: Boolean;
|
||||||
|
isLongTime: Boolean;
|
||||||
|
isMilliSec: Boolean;
|
||||||
|
t,d: Boolean;
|
||||||
|
begin
|
||||||
|
ANumberFormat := nfGeneral;
|
||||||
|
ANumberFormatStr := '';
|
||||||
|
ADecimals := 0;
|
||||||
|
|
||||||
|
lFormatData := FindFormatDataForCell(AXFIndex);
|
||||||
|
{Record FORMAT, BIFF 5/8 (5.49):
|
||||||
|
Offset Size Contents
|
||||||
|
0 2 Format index used in other records
|
||||||
|
}
|
||||||
|
|
||||||
|
if lFormatData = nil then begin
|
||||||
|
// no custom format, so first test for default formats
|
||||||
|
lXFData := TXFListData (FXFList.Items[AXFIndex]);
|
||||||
|
case lXFData.FormatIndex of
|
||||||
|
FORMAT_DATE_DM:
|
||||||
|
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'DM'; end;
|
||||||
|
FORMAT_DATE_MY:
|
||||||
|
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'MY'; end;
|
||||||
|
FORMAT_TIME_MS:
|
||||||
|
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'MS'; end;
|
||||||
|
FORMAT_TIME_MSZ:
|
||||||
|
begin ANumberFormat := nfFmtDateTime; ANumberFormatStr := 'MSZ'; end;
|
||||||
|
else
|
||||||
|
if (lXFData.FormatIndex > 0) and (lXFData.FormatIndex <= 58) then begin
|
||||||
|
ANumberFormat := fmts[lXFData.FormatIndex];
|
||||||
|
ADecimals := decs[lXFData.FormatIndex];
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
// Check custom formats if they have "/" in format string (this can fail for
|
||||||
|
// custom text formats)
|
||||||
|
if IsPercentNumberFormat(lFormatData.FormatString, ADecimals) then
|
||||||
|
ANumberFormat := nfPercentage
|
||||||
|
else
|
||||||
|
if IsExpNumberFormat(lFormatData.Formatstring, ADecimals) then
|
||||||
|
ANumberFormat := nfExp
|
||||||
|
else
|
||||||
|
if IsThousandSepNumberFormat(lFormatData.FormatString, ADecimals) then
|
||||||
|
ANumberFormat := nfFixedTh
|
||||||
|
else
|
||||||
|
if IsFixedNumberFormat(lFormatData.FormatString, ADecimals) then
|
||||||
|
ANumberFormat := nfFixed
|
||||||
|
else begin
|
||||||
|
t := IsTimeFormat(lFormatData.FormatString, isLongTime, isAMPM, isMilliSec);
|
||||||
|
d := IsDateFormat(lFormatData.FormatString);
|
||||||
|
if d and t then
|
||||||
|
ANumberFormat := nfShortDateTime
|
||||||
|
else
|
||||||
|
if d then
|
||||||
|
ANumberFormat := nfShortDate
|
||||||
|
else
|
||||||
|
if t then begin
|
||||||
|
if isAMPM then begin
|
||||||
|
if isLongTime then
|
||||||
|
ANumberFormat := nfLongTimeAM
|
||||||
|
else
|
||||||
|
ANumberFormat := nfShortTimeAM;
|
||||||
|
end else begin
|
||||||
|
if isLongTime then
|
||||||
|
ANumberFormat := nfLongTime
|
||||||
|
else
|
||||||
|
ANumberFormat := nfShortTime;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Determines the format data (for numerical formatting) which belong to a given
|
||||||
|
XF record.
|
||||||
|
Does not return data for built-in formats. }
|
||||||
|
function TsSpreadBIFFReader.FindFormatDataForCell(const AXFIndex: Integer
|
||||||
|
): TFormatListData;
|
||||||
|
var
|
||||||
|
lXFData: TXFListData;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
lXFData := TXFListData(FXFList.Items[AXFIndex]);
|
||||||
|
for i := 0 to FFormatList.Count-1 do begin
|
||||||
|
Result := TFormatListData(FFormatList.Items[i]);
|
||||||
|
if Result.Index = lXFData.FormatIndex then Exit;
|
||||||
|
end;
|
||||||
|
Result := nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Convert the number to a date/time and return that if it is }
|
||||||
|
function TsSpreadBIFFReader.IsDateTime(Number: Double;
|
||||||
|
ANumberFormat: TsNumberFormat; var ADateTime: TDateTime): boolean;
|
||||||
|
begin
|
||||||
|
if ANumberFormat in [
|
||||||
|
nfShortDateTime, nfFmtDateTime, nfShortDate,
|
||||||
|
nfShortTime, nfLongTime, nfShortTimeAM, nfLongTimeAM] then
|
||||||
|
begin
|
||||||
|
ADateTime := ConvertExcelDateTimeToDateTime(Number, FDateMode);
|
||||||
|
Result := true;
|
||||||
|
end else
|
||||||
|
if ANumberFormat = nfTimeInterval then begin
|
||||||
|
ADateTime := Number;
|
||||||
|
Result := true;
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
ADateTime := 0;
|
||||||
|
Result := false;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
// In BIFF 8 it seams to always use the UTF-16 codepage
|
// In BIFF 8 it seams to always use the UTF-16 codepage
|
||||||
procedure TsSpreadBIFFReader.ReadCodePage(AStream: TStream);
|
procedure TsSpreadBIFFReader.ReadCodePage(AStream: TStream);
|
||||||
var
|
var
|
||||||
@@ -588,6 +755,40 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Read the FORMAT record for formatting numerical data
|
||||||
|
procedure TsSpreadBIFFReader.ReadFormat(AStream: TStream);
|
||||||
|
begin
|
||||||
|
// to be overridden
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Reads a floating point number and seeks the number format
|
||||||
|
// NOTE: This procedure is valid after BIFF 3.
|
||||||
|
procedure TsSpreadBIFFReader.ReadNumber(AStream: TStream);
|
||||||
|
var
|
||||||
|
ARow, ACol: Cardinal;
|
||||||
|
XF: WORD;
|
||||||
|
AValue: Double;
|
||||||
|
lDateTime: TDateTime;
|
||||||
|
nf: TsNumberFormat;
|
||||||
|
nd: word;
|
||||||
|
nfs: String;
|
||||||
|
begin
|
||||||
|
ReadRowColXF(AStream,ARow,ACol,XF);
|
||||||
|
|
||||||
|
{ IEE 754 floating-point value }
|
||||||
|
AStream.ReadBuffer(AValue, 8);
|
||||||
|
|
||||||
|
{Find out what cell type, set content type and value}
|
||||||
|
ExtractNumberFormat(XF, nf, nd, nfs);
|
||||||
|
if IsDateTime(AValue, nf, lDateTime) then
|
||||||
|
FWorksheet.WriteDateTime(ARow, ACol, lDateTime, nf, nfs)
|
||||||
|
else
|
||||||
|
FWorksheet.WriteNumber(ARow, ACol, AValue, nf, nd);
|
||||||
|
|
||||||
|
{ Add attributes to cell }
|
||||||
|
ApplyCellFormatting(ARow, ACol, XF);
|
||||||
|
end;
|
||||||
|
|
||||||
// Read the palette
|
// Read the palette
|
||||||
procedure TsSpreadBIFFReader.ReadPalette(AStream: TStream);
|
procedure TsSpreadBIFFReader.ReadPalette(AStream: TStream);
|
||||||
var
|
var
|
||||||
@@ -605,8 +806,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Read the row, column and xf index
|
// Read the row, column and xf index
|
||||||
procedure TsSpreadBIFFReader.ReadRowColXF(AStream: TStream; out ARow,
|
procedure TsSpreadBIFFReader.ReadRowColXF(AStream: TStream;
|
||||||
ACol, AXF: WORD);
|
out ARow, ACol: Cardinal; out AXF: WORD);
|
||||||
begin
|
begin
|
||||||
{ BIFF Record data for row and column}
|
{ BIFF Record data for row and column}
|
||||||
ARow := WordLEToN(AStream.ReadWord);
|
ARow := WordLEToN(AStream.ReadWord);
|
||||||
@@ -915,6 +1116,20 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Writes a date/time/datetime to a Biff 5/8 NUMBER record, with a date/time format
|
||||||
|
(There is no separate date record type in xls) }
|
||||||
|
procedure TsSpreadBIFFWriter.WriteDateTime(AStream: TStream; const ARow,
|
||||||
|
ACol: Cardinal; const AValue: TDateTime; ACell: PCell);
|
||||||
|
var
|
||||||
|
ExcelDateSerial: double;
|
||||||
|
begin
|
||||||
|
ExcelDateSerial := ConvertDateTimeToExcelDateTime(AValue,FDateMode);
|
||||||
|
// fpspreadsheet must already have set formatting to a date/datetime format, so
|
||||||
|
// this will get written out as a pointer to the relevant XF record.
|
||||||
|
// In the end, dates in xls are just numbers with a format. Pass it on to WriteNumber:
|
||||||
|
WriteNumber(AStream, ARow, ACol, ExcelDateSerial, ACell);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadBIFFWriter.WritePalette(AStream: TStream);
|
procedure TsSpreadBIFFWriter.WritePalette(AStream: TStream);
|
||||||
var
|
var
|
||||||
i, n: Integer;
|
i, n: Integer;
|
||||||
|
Reference in New Issue
Block a user