fpspreadsheet: Read results of formulas that return strings

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3045 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-05-14 16:30:33 +00:00
parent c36a5e80ce
commit c3f5600c0d
7 changed files with 172 additions and 69 deletions

View File

@ -69,6 +69,13 @@ begin
MyRPNFormula[2].ElementKind := fekROUND; MyRPNFormula[2].ElementKind := fekROUND;
MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula); MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);
// Write a string formula to G1 = "A" & "B"
MyWorksheet.WriteRPNFormula(0, 6, CreateRPNFormula(
RPNString('A',
RPNSTring('B',
RPNFunc(fekConcat,
nil)))));
// Write some string cells // Write some string cells
MyWorksheet.WriteUTF8Text(1, 0, 'First'); MyWorksheet.WriteUTF8Text(1, 0, 'First');
MyWorksheet.WriteFont(1, 0, 'Arial', 12, [fssBold, fssItalic, fssUnderline], scRed); MyWorksheet.WriteFont(1, 0, 'Arial', 12, [fssBold, fssItalic, fssUnderline], scRed);

View File

@ -156,7 +156,14 @@ begin
MyRPNFormula[1].ElementKind := fekABS; MyRPNFormula[1].ElementKind := fekABS;
MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula); MyWorksheet.WriteRPNFormula(0, 5, MyRPNFormula);
r:= 10; // Write a string formula to G1 = "A" & "B"
MyWorksheet.WriteRPNFormula(0, 6, CreateRPNFormula(
RPNString('A',
RPNSTring('B',
RPNFunc(fekConcat,
nil)))));
r := 10;
// Write current date/time to cells B11:B16 // Write current date/time to cells B11:B16
MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDate'); MyWorksheet.WriteUTF8Text(r, 0, 'nfShortDate');
MyWorksheet.WriteDateTime(r, 1, now, nfShortDate); MyWorksheet.WriteDateTime(r, 1, now, nfShortDate);

View File

@ -126,7 +126,6 @@
<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="309"/> <TopLine Value="309"/>
@ -143,9 +142,6 @@
<TopLine Value="2539"/> <TopLine Value="2539"/>
<CursorPos X="19" Y="2550"/> <CursorPos X="19" Y="2550"/>
<UsageCount Value="100"/> <UsageCount Value="100"/>
<Bookmarks Count="1">
<Item0 X="33" Y="1214" ID="1"/>
</Bookmarks>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit2> </Unit2>
<Unit3> <Unit3>
@ -266,9 +262,12 @@
<UnitName Value="xlsbiff8"/> <UnitName Value="xlsbiff8"/>
<EditorIndex Value="5"/> <EditorIndex Value="5"/>
<WindowIndex Value="0"/> <WindowIndex Value="0"/>
<TopLine Value="61"/> <TopLine Value="1747"/>
<CursorPos X="26" Y="70"/> <CursorPos X="1" Y="1764"/>
<UsageCount Value="78"/> <UsageCount Value="78"/>
<Bookmarks Count="1">
<Item0 X="1" Y="1761" ID="1"/>
</Bookmarks>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit17> </Unit17>
<Unit18> <Unit18>
@ -291,8 +290,8 @@
<UnitName Value="xlscommon"/> <UnitName Value="xlscommon"/>
<EditorIndex Value="4"/> <EditorIndex Value="4"/>
<WindowIndex Value="0"/> <WindowIndex Value="0"/>
<TopLine Value="1139"/> <TopLine Value="1207"/>
<CursorPos X="12" Y="1157"/> <CursorPos X="1" Y="1217"/>
<UsageCount Value="74"/> <UsageCount Value="74"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit20> </Unit20>
@ -301,18 +300,19 @@
<UnitName Value="xlsbiff5"/> <UnitName Value="xlsbiff5"/>
<EditorIndex Value="6"/> <EditorIndex Value="6"/>
<WindowIndex Value="0"/> <WindowIndex Value="0"/>
<TopLine Value="1230"/> <TopLine Value="1363"/>
<CursorPos X="39" Y="1257"/> <CursorPos X="1" Y="1364"/>
<UsageCount Value="61"/> <UsageCount Value="61"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit21> </Unit21>
<Unit22> <Unit22>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff2.pas"/>
<UnitName Value="xlsbiff2"/> <UnitName Value="xlsbiff2"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="7"/> <EditorIndex Value="7"/>
<WindowIndex Value="0"/> <WindowIndex Value="0"/>
<TopLine Value="225"/> <TopLine Value="664"/>
<CursorPos X="37" Y="224"/> <CursorPos X="30" Y="687"/>
<UsageCount Value="62"/> <UsageCount Value="62"/>
<Loaded Value="True"/> <Loaded Value="True"/>
</Unit22> </Unit22>
@ -574,123 +574,127 @@
<UsageCount Value="12"/> <UsageCount Value="12"/>
</Unit56> </Unit56>
</Units> </Units>
<JumpHistory Count="29" HistoryIndex="28"> <JumpHistory Count="30" HistoryIndex="29">
<Position1> <Position1>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1365" Column="1" TopLine="1346"/> <Caret Line="1755" Column="19" TopLine="1715"/>
</Position1> </Position1>
<Position2> <Position2>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1366" Column="1" TopLine="1346"/> <Caret Line="1964" Column="1" TopLine="1924"/>
</Position2> </Position2>
<Position3> <Position3>
<Filename Value="..\..\xlsbiff8.pas"/> <Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1624" Column="1" TopLine="1621"/> <Caret Line="1210" Column="81" TopLine="1176"/>
</Position3> </Position3>
<Position4> <Position4>
<Filename Value="..\..\xlsbiff8.pas"/> <Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1627" Column="1" TopLine="1621"/> <Caret Line="1959" Column="1" TopLine="1919"/>
</Position4> </Position4>
<Position5> <Position5>
<Filename Value="..\..\xlsbiff8.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1630" Column="1" TopLine="1621"/> <Caret Line="41" Column="1" TopLine="41"/>
</Position5> </Position5>
<Position6> <Position6>
<Filename Value="..\..\xlsbiff8.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1633" Column="1" TopLine="1621"/> <Caret Line="1753" Column="1" TopLine="1738"/>
</Position6> </Position6>
<Position7> <Position7>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="11" Column="45" TopLine="1"/> <Caret Line="1968" Column="1" TopLine="1928"/>
</Position7> </Position7>
<Position8> <Position8>
<Filename Value="..\..\xlsbiff5.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1" Column="1" TopLine="1"/> <Caret Line="1" Column="1" TopLine="1"/>
</Position8> </Position8>
<Position9> <Position9>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="563" Column="1" TopLine="547"/> <Caret Line="80" Column="21" TopLine="47"/>
</Position9> </Position9>
<Position10> <Position10>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="351" Column="26" TopLine="340"/> <Caret Line="1760" Column="1" TopLine="1744"/>
</Position10> </Position10>
<Position11> <Position11>
<Filename Value="..\..\xlsbiff8.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1611" Column="1" TopLine="1582"/> <Caret Line="95" Column="22" TopLine="75"/>
</Position11> </Position11>
<Position12> <Position12>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1034" Column="35" TopLine="1026"/> <Caret Line="1" Column="1" TopLine="1"/>
</Position12> </Position12>
<Position13> <Position13>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="2021" Column="1" TopLine="1991"/> <Caret Line="1524" Column="37" TopLine="1516"/>
</Position13> </Position13>
<Position14> <Position14>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="82" Column="57" TopLine="52"/> <Caret Line="1649" Column="21" TopLine="1622"/>
</Position14> </Position14>
<Position15> <Position15>
<Filename Value="..\..\xlsbiff2.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1702" Column="5" TopLine="1672"/> <Caret Line="1527" Column="3" TopLine="1524"/>
</Position15> </Position15>
<Position16> <Position16>
<Filename Value="..\..\fpsutils.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="634" Column="32" TopLine="609"/> <Caret Line="1758" Column="3" TopLine="1733"/>
</Position16> </Position16>
<Position17> <Position17>
<Filename Value="..\..\fpsutils.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="629" Column="17" TopLine="612"/> <Caret Line="1" Column="1" TopLine="1"/>
</Position17> </Position17>
<Position18> <Position18>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="266" Column="28" TopLine="244"/> <Caret Line="51" Column="19" TopLine="18"/>
</Position18> </Position18>
<Position19> <Position19>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1150" Column="3" TopLine="1136"/> <Caret Line="57" Column="11" TopLine="24"/>
</Position19> </Position19>
<Position20> <Position20>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="386" Column="15" TopLine="370"/> <Caret Line="67" Column="13" TopLine="34"/>
</Position20> </Position20>
<Position21> <Position21>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1938" Column="1" TopLine="1908"/> <Caret Line="1394" Column="3" TopLine="1388"/>
</Position21> </Position21>
<Position22> <Position22>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1" Column="1" TopLine="1"/> <Caret Line="1761" Column="3" TopLine="1738"/>
</Position22> </Position22>
<Position23> <Position23>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="393" Column="20" TopLine="368"/> <Caret Line="95" Column="75" TopLine="76"/>
</Position23> </Position23>
<Position24> <Position24>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="796" Column="35" TopLine="771"/> <Caret Line="1749" Column="8" TopLine="1747"/>
</Position24> </Position24>
<Position25> <Position25>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="980" Column="14" TopLine="956"/> <Caret Line="95" Column="55" TopLine="95"/>
</Position25> </Position25>
<Position26> <Position26>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1038" Column="14" TopLine="1013"/> <Caret Line="1748" Column="49" TopLine="1733"/>
</Position26> </Position26>
<Position27> <Position27>
<Filename Value="..\..\xlscommon.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1073" Column="12" TopLine="1048"/> <Caret Line="95" Column="55" TopLine="95"/>
</Position27> </Position27>
<Position28> <Position28>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="524" Column="36" TopLine="519"/> <Caret Line="1749" Column="8" TopLine="1747"/>
</Position28> </Position28>
<Position29> <Position29>
<Filename Value="..\..\fpspreadsheet.pas"/> <Filename Value="..\..\xlsbiff5.pas"/>
<Caret Line="1" Column="1" TopLine="1"/> <Caret Line="1370" Column="1" TopLine="1358"/>
</Position29> </Position29>
<Position30>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="39" Column="3" TopLine="10"/>
</Position30>
</JumpHistory> </JumpHistory>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -70,6 +70,7 @@ type
procedure ReadNumber(AStream: TStream); override; procedure ReadNumber(AStream: TStream); override;
procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); override; procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); override;
procedure ReadRowInfo(AStream: TStream); override; procedure ReadRowInfo(AStream: TStream); override;
procedure ReadStringRecord(AStream: TStream; var AStringResult: String); override;
procedure ReadWindow2(AStream: TStream); override; procedure ReadWindow2(AStream: TStream); override;
procedure ReadXF(AStream: TStream); procedure ReadXF(AStream: TStream);
public public
@ -662,6 +663,30 @@ begin
end; end;
end; end;
{ Reads a STRING record which contains the result of string formula. }
procedure TsSpreadBIFF2Reader.ReadStringRecord(AStream: TStream;
var AStringResult: String);
var
record_id: Word;
record_size: word;
len: Byte;
s: ansistring;
begin
record_id := WordLEToN(AStream.ReadWord);
if record_id <> INT_EXCEL_ID_STRING then
raise Exception.Create('ReadStringRecord: wrong record found.');
record_size := WordLEToN(AStream.ReadWord);
// The string is a byte-string with 16 bit length
len := AStream.ReadByte;
if len > 0 then begin
SetLength(s, Len);
AStream.ReadBuffer(s[1], len);
end else
s := '';
AStringResult := s;
end;
{ Reads the WINDOW2 record containing information like "show grid lines", { Reads the WINDOW2 record containing information like "show grid lines",
"show sheet headers", "panes are frozen", etc. } "show sheet headers", "panes are frozen", etc. }
procedure TsSpreadBIFF2Reader.ReadWindow2(AStream: TStream); procedure TsSpreadBIFF2Reader.ReadWindow2(AStream: TStream);

View File

@ -89,6 +89,7 @@ type
procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook); procedure ReadWorksheet(AStream: TStream; AData: TsWorkbook);
procedure ReadBoundsheet(AStream: TStream); procedure ReadBoundsheet(AStream: TStream);
procedure ReadRichString(AStream: TStream); procedure ReadRichString(AStream: TStream);
procedure ReadStringRecord(AStream: TStream; var AStringResult: String); override;
procedure ReadXF(AStream: TStream); procedure ReadXF(AStream: TStream);
public public
{ General reading methods } { General reading methods }
@ -1360,6 +1361,30 @@ begin
ApplyCellFormatting(ARow, ACol, XF); ApplyCellFormatting(ARow, ACol, XF);
end; end;
{ Reads a STRING record which contains the result of string formula. }
procedure TsSpreadBIFF5Reader.ReadStringRecord(AStream: TStream;
var AStringResult: String);
var
record_id: Word;
record_size: word;
len: Word;
s: ansistring;
begin
record_id := WordLEToN(AStream.ReadWord);
if record_id <> INT_EXCEL_ID_STRING then
raise Exception.Create('ReadStringRecord: wrong record found.');
record_size := WordLEToN(AStream.ReadWord);
// The string is a byte-string with 16 bit length
len := WordLEToN(AStream.ReadWord);
if len > 0 then begin
SetLength(s, Len);
AStream.ReadBuffer(s[1], len);
end else
s := '';
AStringResult := s;
end;
procedure TsSpreadBIFF5Reader.ReadFromFile(AFileName: string; AData: TsWorkbook); procedure TsSpreadBIFF5Reader.ReadFromFile(AFileName: string; AData: TsWorkbook);
var var
MemStream: TMemoryStream; MemStream: TMemoryStream;

View File

@ -91,6 +91,8 @@ type
procedure ReadBlank(AStream: TStream); override; procedure ReadBlank(AStream: TStream); override;
procedure ReadLabel(AStream: TStream); override; procedure ReadLabel(AStream: TStream); override;
procedure ReadRichString(const AStream: TStream); procedure ReadRichString(const AStream: TStream);
protected
procedure ReadStringRecord(AStream: TStream; var AStringResult: String); override;
public public
destructor Destroy; override; destructor Destroy; override;
{ General reading methods } { General reading methods }
@ -1743,6 +1745,23 @@ begin
ApplyCellFormatting(ARow, ACol, XF); ApplyCellFormatting(ARow, ACol, XF);
end; end;
procedure TsSpreadBIFF8Reader.ReadStringRecord(AStream: TStream;
var AStringResult: String);
var
record_id: Word;
record_size: word;
p: Cardinal;
begin
record_id := WordLEToN(AStream.ReadWord);
if record_id <> INT_EXCEL_ID_STRING then
raise Exception.Create('ReadStringRecord: wrong record found.');
record_size := WordLEToN(AStream.ReadWord);
p := AStream.Position;
AStringResult := ReadWideString(AStream, false);
AStream.Position := p + record_size;
end;
procedure TsSpreadBIFF8Reader.ReadXF(const AStream: TStream); procedure TsSpreadBIFF8Reader.ReadXF(const AStream: TStream);
function FixLineStyle(dw: DWord): TsLineStyle; function FixLineStyle(dw: DWord): TsLineStyle;

View File

@ -36,6 +36,7 @@ const
INT_EXCEL_ID_BLANK = $0201; // BIFF2: $0001 INT_EXCEL_ID_BLANK = $0201; // BIFF2: $0001
INT_EXCEL_ID_NUMBER = $0203; // BIFF2: $0003 INT_EXCEL_ID_NUMBER = $0203; // BIFF2: $0003
INT_EXCEL_ID_LABEL = $0204; // BIFF2: $0004 INT_EXCEL_ID_LABEL = $0204; // BIFF2: $0004
INT_EXCEL_ID_STRING = $0207; // BIFF2: $0007;
INT_EXCEL_ID_ROW = $0208; // BIFF2: $0008 INT_EXCEL_ID_ROW = $0208; // BIFF2: $0008
INT_EXCEL_ID_INDEX = $020B; // BIFF2: $000B INT_EXCEL_ID_INDEX = $020B; // BIFF2: $000B
INT_EXCEL_ID_WINDOW2 = $023E; // BIFF2: $003E INT_EXCEL_ID_WINDOW2 = $023E; // BIFF2: $003E
@ -417,6 +418,8 @@ type
procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); virtual; procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); virtual;
// Read row info // Read row info
procedure ReadRowInfo(AStream: TStream); virtual; procedure ReadRowInfo(AStream: TStream); virtual;
// Read STRING record (result of string formula)
procedure ReadStringRecord(AStream: TStream; var AResultString: String); virtual;
// Read WINDOW2 record (gridlines, sheet headers) // Read WINDOW2 record (gridlines, sheet headers)
procedure ReadWindow2(AStream: TStream); virtual; procedure ReadWindow2(AStream: TStream); virtual;
public public
@ -939,6 +942,7 @@ var
nf: TsNumberFormat; nf: TsNumberFormat;
nd: Word; nd: Word;
nfs: String; nfs: String;
resultStr: String;
begin begin
{ BIFF Record header } { BIFF Record header }
@ -969,7 +973,10 @@ begin
if (Data[6] = $FF) and (Data[7] = $FF) then if (Data[6] = $FF) and (Data[7] = $FF) then
case Data[0] of case Data[0] of
0: FWorksheet.WriteUTF8Text(ARow, ACol, '(String)'); 0: begin
ReadStringRecord(AStream, resultStr);
FWorksheet.WriteUTF8Text(ARow, ACol, resultStr);
end;
1: FWorksheet.WriteUTF8Text(ARow, ACol, '(Bool)'); 1: FWorksheet.WriteUTF8Text(ARow, ACol, '(Bool)');
2: FWorksheet.WriteUTF8Text(ARow, ACol, '(ERROR)'); 2: FWorksheet.WriteUTF8Text(ARow, ACol, '(ERROR)');
3: FWorksheet.WriteUTF8Text(ARow, ACol, '(empty)'); 3: FWorksheet.WriteUTF8Text(ARow, ACol, '(empty)');
@ -1199,6 +1206,15 @@ begin
// changed manually. // changed manually.
end; end;
{ Reads a STRING record. It immediately precedes a FORMULA record which has a
string result.
Returns here just a dummy string. Has to be overridden to read the real text. }
procedure TsSpreadBIFFReader.ReadStringRecord(AStream: TStream;
var AResultString: String);
begin
AResultString := '(STRING)';
end;
{ Reads the WINDOW2 record containing information like "show grid lines", { Reads the WINDOW2 record containing information like "show grid lines",
"show sheet headers", "panes are frozen", etc. "show sheet headers", "panes are frozen", etc.
The record structure is slightly different for BIFF5 and BIFF8, but we use The record structure is slightly different for BIFF5 and BIFF8, but we use