fpspreadsheet: Initial implementation of a number format parser. Not complete yet.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3061 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-05-19 22:26:42 +00:00
parent 16cce8f134
commit cb9d07d0dd
11 changed files with 1052 additions and 224 deletions

View File

@ -42,16 +42,19 @@ begin
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet1);
MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines];
{
MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes];
myWorksheet.LeftPaneWidth := 1;
MyWorksheet.TopPaneHeight := 2;
}
{ non-frozen panes not working, at the moment. Requires SELECTION records?
MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm
}
// Write some cells
MyWorksheet.WriteNumber(0, 0, 1.0);// A1
// MyWorksheet.WriteNumber(0, 0, 1.0);// A1
MyWorksheet.WriteNumber(0, 0, 1.0, nfFixed, 3);// A1
MyWorksheet.WriteNumber(0, 1, 2.0);// B1
MyWorksheet.WriteNumber(0, 2, 3.0);// C1
MyWorksheet.WriteNumber(0, 3, 4.0);// D1

View File

@ -107,7 +107,7 @@
<PackageName Value="LCL"/>
</Item2>
</RequiredPackages>
<Units Count="59">
<Units Count="60">
<Unit0>
<Filename Value="fpsgrid.lpr"/>
<IsPartOfProject Value="True"/>
@ -131,26 +131,24 @@
<TopLine Value="394"/>
<CursorPos X="40" Y="412"/>
<UsageCount Value="200"/>
<Bookmarks Count="1">
<Item0 X="3" Y="361" ID="1"/>
</Bookmarks>
<Loaded Value="True"/>
<LoadedDesigner Value="True"/>
</Unit1>
<Unit2>
<Filename Value="..\..\fpspreadsheet.pas"/>
<UnitName Value="fpspreadsheet"/>
<EditorIndex Value="4"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="6"/>
<WindowIndex Value="0"/>
<TopLine Value="2748"/>
<CursorPos X="1" Y="2748"/>
<TopLine Value="132"/>
<CursorPos X="16" Y="164"/>
<UsageCount Value="100"/>
<Loaded Value="True"/>
</Unit2>
<Unit3>
<Filename Value="..\..\fpspreadsheetgrid.pas"/>
<UnitName Value="fpspreadsheetgrid"/>
<EditorIndex Value="5"/>
<EditorIndex Value="8"/>
<WindowIndex Value="0"/>
<TopLine Value="636"/>
<CursorPos X="20" Y="647"/>
@ -163,7 +161,7 @@
<WindowIndex Value="0"/>
<TopLine Value="25"/>
<CursorPos X="4" Y="44"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit4>
<Unit5>
<Filename Value="c:\lazarus27\fpc\2.2.4\source\packages\winunits-base\src\activex.pp"/>
@ -171,7 +169,7 @@
<WindowIndex Value="0"/>
<TopLine Value="49"/>
<CursorPos X="10" Y="24"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit5>
<Unit6>
<Filename Value="c:\lazarus27\fpc\2.2.4\source\packages\fcl-base\src\avl_tree.pp"/>
@ -179,7 +177,7 @@
<WindowIndex Value="0"/>
<TopLine Value="37"/>
<CursorPos X="14" Y="83"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit6>
<Unit7>
<Filename Value="c:\Lazarus\lcl\grids.pas"/>
@ -187,14 +185,14 @@
<WindowIndex Value="0"/>
<TopLine Value="1516"/>
<CursorPos X="28" Y="1534"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit7>
<Unit8>
<Filename Value="c:\Lazarus\lcl\include\customform.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="2021"/>
<CursorPos X="1" Y="2041"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit8>
<Unit9>
<Filename Value="..\..\fpsallformats.pas"/>
@ -202,7 +200,7 @@
<WindowIndex Value="0"/>
<TopLine Value="1"/>
<CursorPos X="62" Y="13"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit9>
<Unit10>
<Filename Value="..\..\wikitable.pas"/>
@ -210,7 +208,7 @@
<WindowIndex Value="0"/>
<TopLine Value="48"/>
<CursorPos X="41" Y="60"/>
<UsageCount Value="11"/>
<UsageCount Value="9"/>
</Unit10>
<Unit11>
<Filename Value="..\..\fpsopendocument.pas"/>
@ -218,7 +216,7 @@
<WindowIndex Value="0"/>
<TopLine Value="1"/>
<CursorPos X="1" Y="1"/>
<UsageCount Value="7"/>
<UsageCount Value="5"/>
</Unit11>
<Unit12>
<Filename Value="d:\lazarus-svn\lcl\grids.pas"/>
@ -226,7 +224,7 @@
<WindowIndex Value="0"/>
<TopLine Value="4852"/>
<CursorPos X="16" Y="4884"/>
<UsageCount Value="47"/>
<UsageCount Value="45"/>
</Unit12>
<Unit13>
<Filename Value="..\..\fpsutils.pas"/>
@ -235,7 +233,7 @@
<WindowIndex Value="0"/>
<TopLine Value="1206"/>
<CursorPos X="21" Y="1222"/>
<UsageCount Value="54"/>
<UsageCount Value="62"/>
<Loaded Value="True"/>
</Unit13>
<Unit14>
@ -243,7 +241,7 @@
<WindowIndex Value="0"/>
<TopLine Value="1212"/>
<CursorPos X="3" Y="1218"/>
<UsageCount Value="3"/>
<UsageCount Value="1"/>
</Unit14>
<Unit15>
<Filename Value="d:\lazarus-svn\lcl\graphics.pp"/>
@ -251,24 +249,23 @@
<WindowIndex Value="0"/>
<TopLine Value="1937"/>
<CursorPos X="11" Y="1956"/>
<UsageCount Value="32"/>
<UsageCount Value="30"/>
</Unit15>
<Unit16>
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\classes\classesh.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="248"/>
<CursorPos X="22" Y="263"/>
<UsageCount Value="11"/>
<UsageCount Value="9"/>
</Unit16>
<Unit17>
<Filename Value="..\..\xlsbiff8.pas"/>
<UnitName Value="xlsbiff8"/>
<IsVisibleTab Value="True"/>
<EditorIndex Value="3"/>
<WindowIndex Value="0"/>
<TopLine Value="1920"/>
<CursorPos X="11" Y="1932"/>
<UsageCount Value="84"/>
<CursorPos X="21" Y="1924"/>
<UsageCount Value="92"/>
<Loaded Value="True"/>
</Unit17>
<Unit18>
@ -277,22 +274,27 @@
<WindowIndex Value="0"/>
<TopLine Value="1091"/>
<CursorPos X="12" Y="1122"/>
<UsageCount Value="7"/>
<UsageCount Value="5"/>
</Unit18>
<Unit19>
<Filename Value="d:\lazarus-svn\lcl\include\wincontrol.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="7344"/>
<CursorPos X="30" Y="7349"/>
<UsageCount Value="5"/>
<UsageCount Value="3"/>
</Unit19>
<Unit20>
<Filename Value="..\..\xlscommon.pas"/>
<UnitName Value="xlscommon"/>
<EditorIndex Value="4"/>
<WindowIndex Value="0"/>
<TopLine Value="509"/>
<CursorPos X="68" Y="517"/>
<UsageCount Value="80"/>
<TopLine Value="1181"/>
<CursorPos X="31" Y="1194"/>
<UsageCount Value="88"/>
<Bookmarks Count="1">
<Item0 X="41" Y="1209" ID="1"/>
</Bookmarks>
<Loaded Value="True"/>
</Unit20>
<Unit21>
<Filename Value="..\..\xlsbiff5.pas"/>
@ -300,7 +302,7 @@
<WindowIndex Value="0"/>
<TopLine Value="76"/>
<CursorPos X="49" Y="92"/>
<UsageCount Value="67"/>
<UsageCount Value="65"/>
</Unit21>
<Unit22>
<Filename Value="..\..\xlsbiff2.pas"/>
@ -308,7 +310,7 @@
<WindowIndex Value="0"/>
<TopLine Value="548"/>
<CursorPos X="1" Y="560"/>
<UsageCount Value="68"/>
<UsageCount Value="66"/>
</Unit22>
<Unit23>
<Filename Value="d:\lazarus-svn\lcl\lclproc.pas"/>
@ -316,7 +318,7 @@
<WindowIndex Value="0"/>
<TopLine Value="841"/>
<CursorPos X="19" Y="852"/>
<UsageCount Value="10"/>
<UsageCount Value="8"/>
</Unit23>
<Unit24>
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\packages\fcl-image\src\fpcanvas.pp"/>
@ -324,384 +326,394 @@
<WindowIndex Value="0"/>
<TopLine Value="111"/>
<CursorPos X="3" Y="112"/>
<UsageCount Value="13"/>
<UsageCount Value="11"/>
</Unit24>
<Unit25>
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\packages\fcl-image\src\fpimage.pp"/>
<UnitName Value="FPimage"/>
<WindowIndex Value="0"/>
<TopLine Value="74"/>
<CursorPos X="3" Y="93"/>
<UsageCount Value="1"/>
</Unit25>
<Unit26>
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\classes\lists.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="141"/>
<CursorPos X="3" Y="143"/>
<UsageCount Value="9"/>
</Unit26>
<Unit27>
<UsageCount Value="7"/>
</Unit25>
<Unit26>
<Filename Value="d:\Prog_Delphi\common\units\XLS.pas"/>
<UnitName Value="Xls"/>
<WindowIndex Value="0"/>
<TopLine Value="114"/>
<CursorPos X="42" Y="152"/>
<UsageCount Value="9"/>
</Unit27>
<Unit28>
<UsageCount Value="7"/>
</Unit26>
<Unit27>
<Filename Value="d:\lazarus-svn\lcl\include\pen.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="354"/>
<CursorPos X="1" Y="385"/>
<UsageCount Value="14"/>
</Unit28>
<Unit29>
<UsageCount Value="12"/>
</Unit27>
<Unit28>
<Filename Value="d:\lazarus-svn\lcl\controls.pp"/>
<UnitName Value="Controls"/>
<WindowIndex Value="0"/>
<TopLine Value="2222"/>
<CursorPos X="14" Y="2242"/>
<UsageCount Value="9"/>
</Unit29>
<Unit30>
<UsageCount Value="7"/>
</Unit28>
<Unit29>
<Filename Value="d:\lazarus-svn\lcl\include\control.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="2696"/>
<CursorPos X="23" Y="2712"/>
<UsageCount Value="10"/>
</Unit30>
<Unit31>
<UsageCount Value="8"/>
</Unit29>
<Unit30>
<Filename Value="..\..\fpspreadsheetchart.pas"/>
<UnitName Value="fpspreadsheetchart"/>
<WindowIndex Value="0"/>
<TopLine Value="170"/>
<CursorPos X="37" Y="204"/>
<UsageCount Value="4"/>
</Unit31>
<Unit32>
<UsageCount Value="2"/>
</Unit30>
<Unit31>
<Filename Value="d:\lazarus-svn\components\lazutils\lazutf8.pas"/>
<UnitName Value="LazUTF8"/>
<WindowIndex Value="0"/>
<TopLine Value="3180"/>
<CursorPos X="1" Y="3212"/>
<UsageCount Value="5"/>
</Unit32>
<Unit33>
<UsageCount Value="3"/>
</Unit31>
<Unit32>
<Filename Value="d:\lazarus-svn\lcl\colorbox.pas"/>
<UnitName Value="ColorBox"/>
<WindowIndex Value="0"/>
<TopLine Value="584"/>
<CursorPos X="3" Y="598"/>
<UsageCount Value="13"/>
</Unit33>
<Unit34>
<UsageCount Value="11"/>
</Unit32>
<Unit33>
<Filename Value="d:\lazarus-svn\lcl\dialogs.pp"/>
<UnitName Value="Dialogs"/>
<WindowIndex Value="0"/>
<TopLine Value="222"/>
<CursorPos X="3" Y="253"/>
<UsageCount Value="5"/>
</Unit34>
<Unit35>
<UsageCount Value="3"/>
</Unit33>
<Unit34>
<Filename Value="d:\lazarus-svn\lcl\forms.pp"/>
<UnitName Value="Forms"/>
<WindowIndex Value="0"/>
<TopLine Value="932"/>
<CursorPos X="3" Y="939"/>
<UsageCount Value="5"/>
</Unit35>
<Unit36>
<UsageCount Value="3"/>
</Unit34>
<Unit35>
<Filename Value="C:\development\lazarus\lcl\graphics.pp"/>
<UnitName Value="Graphics"/>
<WindowIndex Value="0"/>
<TopLine Value="2053"/>
<CursorPos X="30" Y="1945"/>
<UsageCount Value="8"/>
</Unit36>
<Unit37>
<UsageCount Value="6"/>
</Unit35>
<Unit36>
<Filename Value="C:\development\fpc\packages\fcl-image\src\fpcanvas.pp"/>
<UnitName Value="FPCanvas"/>
<WindowIndex Value="0"/>
<TopLine Value="89"/>
<CursorPos X="15" Y="97"/>
<UsageCount Value="7"/>
</Unit37>
<Unit38>
<UsageCount Value="5"/>
</Unit36>
<Unit37>
<Filename Value="C:\development\fpc\packages\fcl-image\src\fpfont.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="54"/>
<CursorPos X="3" Y="57"/>
<UsageCount Value="7"/>
</Unit38>
<Unit39>
<UsageCount Value="5"/>
</Unit37>
<Unit38>
<Filename Value="C:\development\lazarus\lcl\graphmath.pp"/>
<UnitName Value="GraphMath"/>
<WindowIndex Value="0"/>
<TopLine Value="584"/>
<CursorPos X="3" Y="439"/>
<UsageCount Value="7"/>
</Unit39>
<Unit40>
<UsageCount Value="5"/>
</Unit38>
<Unit39>
<Filename Value="C:\development\lazarus\lcl\graphtype.pp"/>
<UnitName Value="GraphType"/>
<WindowIndex Value="0"/>
<TopLine Value="234"/>
<CursorPos X="3" Y="33"/>
<UsageCount Value="7"/>
</Unit40>
<Unit41>
<UsageCount Value="5"/>
</Unit39>
<Unit40>
<Filename Value="C:\development\lazarus\lcl\lcltype.pp"/>
<UnitName Value="LCLType"/>
<WindowIndex Value="0"/>
<TopLine Value="1628"/>
<CursorPos X="3" Y="1643"/>
<UsageCount Value="7"/>
</Unit41>
<Unit42>
<UsageCount Value="5"/>
</Unit40>
<Unit41>
<Filename Value="C:\development\lazarus\lcl\graphutil.pp"/>
<UnitName Value="GraphUtil"/>
<WindowIndex Value="0"/>
<TopLine Value="128"/>
<CursorPos X="12" Y="143"/>
<UsageCount Value="7"/>
</Unit42>
<Unit43>
<UsageCount Value="5"/>
</Unit41>
<Unit42>
<Filename Value="C:\development\fpc\rtl\objpas\math.pp"/>
<UnitName Value="math"/>
<WindowIndex Value="0"/>
<TopLine Value="144"/>
<CursorPos X="10" Y="159"/>
<UsageCount Value="10"/>
</Unit43>
<Unit44>
<UsageCount Value="8"/>
</Unit42>
<Unit43>
<Filename Value="C:\development\fpc\rtl\i386\i386.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="1497"/>
<CursorPos X="1" Y="1515"/>
<UsageCount Value="13"/>
</Unit44>
<Unit45>
<UsageCount Value="11"/>
</Unit43>
<Unit44>
<Filename Value="C:\development\lazarus\lcl\grids.pas"/>
<UnitName Value="Grids"/>
<WindowIndex Value="0"/>
<TopLine Value="794"/>
<CursorPos X="15" Y="1010"/>
<UsageCount Value="14"/>
</Unit45>
<Unit46>
<UsageCount Value="12"/>
</Unit44>
<Unit45>
<Filename Value="..\..\..\spktoolbar\SpkGraphTools\SpkGraphTools.pas"/>
<UnitName Value="SpkGraphTools"/>
<WindowIndex Value="0"/>
<TopLine Value="136"/>
<CursorPos X="1" Y="143"/>
<UsageCount Value="5"/>
</Unit46>
<Unit47>
<UsageCount Value="3"/>
</Unit45>
<Unit46>
<Filename Value="C:\development\fpc\rtl\objpas\classes\lists.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="34"/>
<CursorPos X="1" Y="49"/>
<UsageCount Value="13"/>
</Unit47>
<Unit48>
<UsageCount Value="11"/>
</Unit46>
<Unit47>
<Filename Value="C:\development\lazarus\lcl\include\canvas.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="1705"/>
<CursorPos X="1" Y="1720"/>
<UsageCount Value="13"/>
</Unit48>
<Unit49>
<UsageCount Value="11"/>
</Unit47>
<Unit48>
<Filename Value="C:\development\lazarus\lcl\include\font.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="1139"/>
<CursorPos X="25" Y="1161"/>
<UsageCount Value="13"/>
</Unit49>
<Unit50>
<UsageCount Value="11"/>
</Unit48>
<Unit49>
<Filename Value="C:\development\lazarus\lcl\include\winapih.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="156"/>
<CursorPos X="10" Y="171"/>
<UsageCount Value="7"/>
</Unit50>
<Unit51>
<UsageCount Value="5"/>
</Unit49>
<Unit50>
<Filename Value="C:\development\lazarus\lcl\include\intfbasewinapi.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="1577"/>
<CursorPos X="3" Y="1579"/>
<UsageCount Value="7"/>
</Unit51>
<Unit52>
<UsageCount Value="5"/>
</Unit50>
<Unit51>
<Filename Value="C:\development\fpc\rtl\inc\except.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="202"/>
<CursorPos X="1" Y="227"/>
<UsageCount Value="12"/>
</Unit52>
<Unit53>
<UsageCount Value="10"/>
</Unit51>
<Unit52>
<Filename Value="d:\lazarus-svn\lcl\include\menuitem.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="69"/>
<CursorPos X="28" Y="82"/>
<UsageCount Value="13"/>
</Unit53>
<Unit54>
<UsageCount Value="11"/>
</Unit52>
<Unit53>
<Filename Value="d:\lazarus-svn\lcl\include\application.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="1371"/>
<CursorPos X="1" Y="1390"/>
<UsageCount Value="12"/>
</Unit54>
<Unit55>
<UsageCount Value="10"/>
</Unit53>
<Unit54>
<Filename Value="d:\lazarus-svn\lcl\include\font.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="648"/>
<CursorPos X="1" Y="675"/>
<UsageCount Value="11"/>
</Unit55>
<Unit56>
<UsageCount Value="9"/>
</Unit54>
<Unit55>
<Filename Value="d:\lazarus-svn\lcl\include\fontdialog.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="24"/>
<CursorPos X="1" Y="49"/>
<UsageCount Value="11"/>
</Unit56>
<Unit57>
<UsageCount Value="9"/>
</Unit55>
<Unit56>
<Filename Value="C:\development\fpc\rtl\objpas\sysutils\sysinth.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="50"/>
<CursorPos X="3" Y="57"/>
<UsageCount Value="10"/>
</Unit57>
<Unit58>
<UsageCount Value="8"/>
</Unit56>
<Unit57>
<Filename Value="C:\development\fpc\rtl\inc\wstrings.inc"/>
<WindowIndex Value="0"/>
<TopLine Value="169"/>
<CursorPos X="1" Y="185"/>
<UsageCount Value="10"/>
<UsageCount Value="8"/>
</Unit57>
<Unit58>
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\sysutils\dati.inc"/>
<EditorIndex Value="5"/>
<WindowIndex Value="0"/>
<TopLine Value="890"/>
<CursorPos X="16" Y="796"/>
<UsageCount Value="15"/>
<Loaded Value="True"/>
</Unit58>
<Unit59>
<Filename Value="d:\lazarus-svn\fpc\2.6.2\source\rtl\objpas\sysutils\sysinth.inc"/>
<EditorIndex Value="7"/>
<WindowIndex Value="0"/>
<TopLine Value="36"/>
<CursorPos X="5" Y="43"/>
<UsageCount Value="13"/>
<Loaded Value="True"/>
</Unit59>
</Units>
<JumpHistory Count="30" HistoryIndex="29">
<Position1>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1437" Column="1" TopLine="1407"/>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position1>
<Position2>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1410" Column="1" TopLine="1403"/>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="164" Column="60" TopLine="132"/>
</Position2>
<Position3>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1411" Column="1" TopLine="1403"/>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="1511" Column="15" TopLine="1478"/>
</Position3>
<Position4>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1412" Column="1" TopLine="1403"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1170" Column="36" TopLine="1170"/>
</Position4>
<Position5>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1414" Column="1" TopLine="1403"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position5>
<Position6>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1416" Column="1" TopLine="1403"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="940" Column="14" TopLine="908"/>
</Position6>
<Position7>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1417" Column="1" TopLine="1403"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="960" Column="14" TopLine="928"/>
</Position7>
<Position8>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1423" Column="1" TopLine="1403"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1013" Column="14" TopLine="982"/>
</Position8>
<Position9>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1437" Column="1" TopLine="1406"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1059" Column="14" TopLine="1027"/>
</Position9>
<Position10>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1929" Column="3" TopLine="1920"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1081" Column="41" TopLine="1049"/>
</Position10>
<Position11>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1567" Column="1" TopLine="1548"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1089" Column="43" TopLine="1057"/>
</Position11>
<Position12>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1934" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1093" Column="14" TopLine="1061"/>
</Position12>
<Position13>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1937" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1157" Column="14" TopLine="1126"/>
</Position13>
<Position14>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1940" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1197" Column="20" TopLine="1177"/>
</Position14>
<Position15>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2761" Column="1" TopLine="2742"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="403" Column="16" TopLine="397"/>
</Position15>
<Position16>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2762" Column="1" TopLine="2742"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="924" Column="14" TopLine="893"/>
</Position16>
<Position17>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2763" Column="1" TopLine="2742"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="413" Column="19" TopLine="402"/>
</Position17>
<Position18>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1925" Column="17" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="414" Column="33" TopLine="388"/>
</Position18>
<Position19>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2765" Column="3" TopLine="2751"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="854" Column="39" TopLine="825"/>
</Position19>
<Position20>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1567" Column="1" TopLine="1548"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="672" Column="1" TopLine="648"/>
</Position20>
<Position21>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1934" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="870" Column="1" TopLine="832"/>
</Position21>
<Position22>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1937" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="867" Column="24" TopLine="848"/>
</Position22>
<Position23>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1940" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="926" Column="34" TopLine="907"/>
</Position23>
<Position24>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2761" Column="1" TopLine="2751"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="956" Column="1" TopLine="937"/>
</Position24>
<Position25>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2762" Column="1" TopLine="2751"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1024" Column="63" TopLine="1006"/>
</Position25>
<Position26>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="2772" Column="1" TopLine="2751"/>
<Caret Line="1478" Column="48" TopLine="1478"/>
</Position26>
<Position27>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1934" Column="1" TopLine="1915"/>
<Filename Value="..\..\fpspreadsheet.pas"/>
<Caret Line="1" Column="1" TopLine="1"/>
</Position27>
<Position28>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1937" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1058" Column="9" TopLine="1039"/>
</Position28>
<Position29>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1940" Column="1" TopLine="1915"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1055" Column="44" TopLine="1039"/>
</Position29>
<Position30>
<Filename Value="..\..\xlsbiff8.pas"/>
<Caret Line="1439" Column="1" TopLine="1421"/>
<Filename Value="..\..\xlscommon.pas"/>
<Caret Line="1135" Column="22" TopLine="1120"/>
</Position30>
</JumpHistory>
</ProjectOptions>
@ -731,6 +743,15 @@
</Other>
</CompilerOptions>
<Debugging>
<BreakPoints Count="1">
<Item1>
<Kind Value="bpkSource"/>
<WatchScope Value="wpsLocal"/>
<WatchKind Value="wpkWrite"/>
<Source Value="..\..\xlscommon.pas"/>
<Line Value="664"/>
</Item1>
</BreakPoints>
<Watches Count="2">
<Item1>
<Expression Value="recordtype"/>

View File

@ -0,0 +1,598 @@
unit fpsNumFormatParser;
{$ifdef fpc}
{$mode delphi}
{$endif}
interface
uses
SysUtils, fpspreadsheet;
const
psOK = 0;
psErrNoValidColorIndex = 1;
psErrNoValidCompareNumber = 2;
psErrUnknownInfoInBrackets = 3;
psErrConditionalFormattingNotSupported = 4;
psErrNoUsableFormat = 5;
psErrNoValidNumberFormat = 6;
psErrNoValidDateTimeFormat = 7;
{ TsNumFormatParser }
type
TsCompareOperation = (coNotUsed,
coEqual, coNotEqual, coLess, coGreater, coLessEqual, coGreaterEqual
);
TsNumFormatSection = record
FormatString: String;
CompareOperation: TsCompareOperation;
CompareValue: Double;
Color: TsColor;
CountryCode: String;
CurrencySymbol: String;
Decimals: Byte;
NumFormat: TsNumberFormat;
end;
TsNumFormatParser = class
private
FWorkbook: TsWorkbook;
FCurrent: PChar;
FStart: PChar;
FEnd: PChar;
FCurrSection: Integer;
FSections: array of TsNumFormatSection;
FFormatSettings: TFormatSettings;
FFormatString: String;
FStatus: Integer;
function GetParsedSectionCount: Integer;
function GetParsedSections(AIndex: Integer): TsNumFormatSection;
protected
procedure AddChar(AChar: Char);
procedure AddSection;
procedure AnalyzeBracket(const AValue: String);
procedure AnalyzeText(const AValue: String);
procedure CheckSections;
procedure Parse(const AFormatString: String);
procedure ScanAMPM(var s: String);
procedure ScanBrackets;
procedure ScanDateTime;
procedure ScanDateTimeParts(TestToken, Replacement: Char; var s: String);
procedure ScanFormat;
procedure ScanNumber;
procedure ScanText;
public
constructor Create(AWorkbook: TsWorkbook; const AFormatString: String);
destructor Destroy; override;
property FormatString: String read FFormatString;
property ParsedSectionCount: Integer read GetParsedSectionCount;
property ParsedSections[AIndex: Integer]: TsNumFormatSection read GetParsedSections;
property Status: Integer read FStatus;
end;
implementation
uses
fpsutils;
const
COMPARE_STR: array[TsCompareOperation] of string = (
'', '=', '<>', '<', '>', '<=', '>'
);
{ TsNumFormatParser }
constructor TsNumFormatParser.Create(AWorkbook: TsWorkbook;
const AFormatString: String);
begin
inherited Create;
FWorkbook := AWorkbook;
FFormatSettings := DefaultFormatSettings;
FFormatSettings.DecimalSeparator := '.';
FFormatSettings.ThousandSeparator := ',';
Parse(AFormatString);
end;
destructor TsNumFormatParser.Destroy;
begin
FSections := nil;
inherited Destroy;
end;
procedure TsNumFormatParser.AddChar(AChar: Char);
begin
with FSections[FCurrSection] do
FormatString := FormatString + AChar;
end;
procedure TsNumFormatParser.AddSection;
begin
FCurrSection := Length(FSections);
SetLength(FSections, FCurrSection + 1);
with FSections[FCurrSection] do begin
FormatString := '';
CompareOperation := coNotUsed;
CompareValue := 0.0;
Color := scBlack;
CountryCode := '';
CurrencySymbol := '';
Decimals := 0;
NumFormat := nfGeneral;
end;
end;
procedure TsNumFormatParser.AnalyzeBracket(const AValue: String);
var
lValue: String;
n: Integer;
begin
lValue := lowercase(AValue);
// Colors
if lValue = 'red' then
FSections[FCurrSection].Color := scRed
else
if lValue = 'black' then
FSections[FCurrSection].Color := scBlack
else
if lValue = 'blue' then
FSections[FCurrSection].Color := scBlue
else
if lValue = 'white' then
FSections[FCurrSection].Color := scWhite
else
if lValue = 'green' then
FSections[FCurrSection].Color := scGreen
else
if lValue = 'cyan' then
FSections[FCurrSection].Color := scCyan
else
if lValue = 'magenta' then
FSections[FCurrSection].Color := scMagenta
else
if copy(lValue, 1, 5) = 'color' then begin
lValue := copy(lValue, 6, Length(lValue));
if not TryStrToInt(trim(lValue), n) then begin
FStatus := psErrNoValidColorIndex;
exit;
end;
FSections[FCurrSection].Color := n;
end
else
// Conditions
if lValue[1] in ['=', '<', '>'] then begin
n := 1;
case lValue[1] of
'=': FSections[FCurrSection].CompareOperation := coEqual;
'<': case lValue[2] of
'>': begin FSections[FCurrSection].CompareOperation := coNotEqual; inc(n); end;
'=': begin FSections[FCurrSection].CompareOperation := coLessEqual; inc(n); end;
else FSections[FCurrSection].CompareOperation := coLess;
end;
'>': case lValue[2] of
'=': begin FSections[FCurrSection].CompareOperation := coGreaterEqual; inc(n); end;
else FSections[FCurrSection].CompareOperation := coGreater;
end;
end;
Delete(lValue, 1, n);
if not TryStrToFloat(trim(lValue), FSections[FCurrSection].CompareValue) then
FStatus := psErrNoValidCompareNumber;
end else
// Locale information
if lValue[1] = '$' then begin
FSections[FCurrSection].CountryCode := Copy(AValue, 2, Length(AValue));
end else
FStatus := psErrUnknownInfoInBrackets;
end;
procedure TsNumFormatParser.AnalyzeText(const AValue: String);
var
uValue: String;
begin
uValue := Uppercase(AValue);
if (uValue = '$') or (uValue = 'USD') or (uValue = '�') or (uValue = 'EUR') or
(uValue = '�') or (uValue = 'GBP') or (uValue = '�') or (uValue = 'JPY')
then
FSections[FCurrSection].CurrencySymbol := AValue;
end;
procedure TsNumFormatParser.CheckSections;
var
i: Integer;
ns: Integer;
s: String;
begin
ns := Length(FSections);
for i:=0 to ns-1 do begin
if FSections[i].FormatString = '' then
FSections[i].NumFormat := nfGeneral;
if (FSections[i].CurrencySymbol <> '') and (FSections[i].NumFormat = nfFixedTh) then
FSections[i].NumFormat := nfCurrency;
if FSections[i].CompareOperation <> coNotUsed then begin
FStatus := psErrConditionalFormattingNotSupported;
exit;
end;
case FSections[i].NumFormat of
nfGeneral, nfFixed, nfFixedTh, nfPercentage, nfExp, nfSci, nfCurrency:
try
s := FormatFloat(FSections[i].FormatString, 1.0, FWorkBook.FormatSettings);
except
FStatus := psErrNoValidNumberFormat;
exit;
end;
nfShortDateTime, nfShortDate, nfShortTime, nfShortTimeAM,
nfLongDate, nfLongTime, nfLongTimeAM, nfFmtDateTime:
try
s := FormatDateTimeEx(FSections[i].FormatString, now(), FWorkbook.FormatSettings);
except
FStatus := psErrNoValidDateTimeFormat;
exit;
end;
end;
end;
if ns = 2 then
FFormatString := Format('%s;%s;%s', [
FSections[0].FormatString,
FSections[1].FormatString,
FSections[0].FormatString // make sure that fpc understands the "zero"
])
else
if ns > 0 then begin
FFormatString := FSections[0].FormatString;
for i:=1 to ns-1 do
FFormatString := Format('%s;%s', [FFormatString, FSections[i].FormatString]);
end else
FStatus := psErrNoUsableFormat;
end;
{
function TsNumFormatParser.GetNumFormat: TsNumberFormat;
var
i: Integer;
begin
if FStatus <> psOK then
Result := nfGeneral
else
if (FSections[0].NumFormat = nfCurrency) and (FSections[1].NumFormat = nfCurrency) and
(FSections[2].NumFormat = nfCurrency)
then begin
if (FSections[1].Color = scNotDefined) then begin
if (FSections[2].FormatString = '-') then
Result := nfCurrencyDash
else
Result := nfCurrency;
end else
if FSections[1].Color = scRed then begin
if (FSections[2].Formatstring = '-') then
Result := nfCurrencyDashRed
else
Result := nfCurrencyRed;
end;
end else
Result := FSections[0].NumFormat;
end;
}
function TsNumFormatParser.GetParsedSectionCount: Integer;
begin
Result := Length(FSections);
end;
function TsNumFormatParser.GetParsedSections(AIndex: Integer): TsNumFormatSection;
begin
Result := FSections[AIndex];
end;
procedure TsNumFormatParser.Parse(const AFormatString: String);
var
token: Char;
begin
FStatus := psOK;
AddSection;
FStart := @AFormatString[1];
FEnd := FStart + Length(AFormatString) - 1;
FCurrent := FStart;
while (FCurrent <= FEnd) and (FStatus = psOK) do begin
token := FCurrent^;
case token of
'[': ScanBrackets;
';': AddSection;
else ScanFormat;
end;
inc(FCurrent);
end;
CheckSections;
end;
{ Extracts the text between square brackets --> AnalyzeBracket }
procedure TsNumFormatParser.ScanBrackets;
var
s: String;
token: Char;
begin
inc(FCurrent); // cursor stands at '['
while (FCurrent <= FEnd) and (FStatus = psOK) do begin
token := FCurrent^;
case token of
']': begin
AnalyzeBracket(s);
break;
end;
else
s := s + token;
end;
inc(FCurrent);
end;
end;
procedure TsNumFormatParser.ScanDateTime;
var
token: Char;
done: Boolean;
s: String;
i: Integer;
nf: TsNumberFormat;
partStr: String;
isTime: Boolean;
isAMPM: Boolean;
begin
done := false;
s := '';
isTime := false;
isAMPM := false;
while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin
token := FCurrent^;
case token of
'\' : begin
inc(FCurrent);
token := FCurrent^;
s := s + token;
end;
'Y', 'y' : begin
ScanDateTimeParts(token, token, s);
isTime := false;
end;
'M', 'm' : if isTime then // help fpc to separate "month" and "minute"
ScanDateTimeParts(token, 'n', s)
else // both "month" and "minute" work in fpc to some degree
ScanDateTimeParts(token, token, s);
'D', 'd' : begin
ScanDateTimeParts(token, token, s);
isTime := false;
end;
'H', 'h' : begin
ScanDateTimeParts(token, token, s);
isTime := true;
end;
'S', 's' : begin
ScanDateTimeParts(token, token, s);
isTime := true;
end;
'/', ':', '.', ']', '[', ' '
: s := s + token;
'0' : ScanDateTimeParts(token, 'z', s);
'A', 'a' : begin
ScanAMPM(s);
isAMPM := true;
end;
else begin
done := true;
dec(FCurrent);
// char pointer must be at end of date/time mask.
end;
end;
if not done then inc(FCurrent);
end;
FSections[FCurrSection].FormatString := FSections[FCurrSection].FormatString + s;
s := FSections[FCurrSection].FormatString;
// Check format
try
if s <> '' then begin
FormatDateTime(s, now);
// !!!! MODIFY TO USE EXTENDED SYNTAX !!!!!
if s = FWorkbook.FormatSettings.LongDateFormat then
nf := nfLongDate
else
if s = FWorkbook.FormatSettings.ShortDateFormat then
nf := nfShortDate
else
if s = FWorkbook.FormatSettings.LongTimeFormat then
nf := nfLongTime
else
if s = FWorkbook.FormatSettings.ShortTimeFormat then
nf := nfShortTime
else
nf := nfFmtDateTime;
FSections[FCurrSection].NumFormat := nf;
end;
except
FStatus := psErrNoValidDateTimeFormat;
end;
end;
procedure TsNumFormatParser.ScanAMPM(var s: String);
var
token: Char;
begin
while (FCurrent <= FEnd) do begin
token := FCurrent^;
if token in ['A', 'a', 'P', 'p', 'm', 'M', '/'] then
s := s + token
else begin
dec(FCurrent);
exit;
end;
inc(FCurrent);
end;
end;
procedure TsNumFormatParser.ScanDateTimeParts(TestToken, Replacement: Char;
var s: String);
var
token: Char;
begin
s := s + Replacement;
while (FCurrent <= FEnd) do begin
inc(FCurrent);
token := FCurrent^;
if token = TestToken then
s := s + Replacement
else begin
dec(FCurrent);
break;
end;
end;
end;
procedure TsNumFormatParser.ScanFormat;
var
token: Char;
done: Boolean;
begin
done := false;
while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin
token := FCurrent^;
case token of
// Strip Excel's formatting symbols
'\', '*' : ;
'_' : inc(FCurrent);
'"' : begin
inc(FCurrent);
ScanText;
end;
'0', '#', '.', ',', '-': ScanNumber;
'y', 'Y', 'm', 'M',
'd', 'D', 'h', 's', '[': ScanDateTime;
' ' : AddChar(token);
';' : begin
done := true;
dec(FCurrent);
// Cursor must stay on the ";"
end;
end;
if not done then inc(FCurrent);
end;
end;
procedure TsNumFormatParser.ScanNumber;
var
token: Char;
done: Boolean;
countdecs: Boolean;
s: String;
hasThSep: Boolean;
isExp: Boolean;
isSci: Boolean;
hasHash: Boolean;
hasPerc: Boolean;
nf: TsNumberFormat;
begin
countdecs := false;
done := false;
hasThSep := false;
hasHash := false;
hasPerc := false;
isExp := false;
isSci := false;
s := '';
while (FCurrent <= FEnd) and (FStatus = psOK) and (not done) do begin
token := FCurrent^;
case token of
',': begin
hasThSep := true;
s := s + token;
end;
'.': begin
countdecs := true;
FSections[FCurrSection].Decimals := 0;
s := s + token;
end;
'0': begin
if countdecs then inc(FSections[FCurrSection].Decimals);
s := s + token;
end;
'E', 'e':
begin
if hasHash and countdecs then isSci := true else isExp := true;
countdecs := false;
s := s + token;
end;
'+', '-':
s := s + token;
'#': begin
hasHash := true;
countdecs := false;
s := s + token;
end;
'%': begin
hasPerc := true;
s := s + token;
end;
else begin
done := true;
dec(FCurrent);
end;
end;
if not done then
inc(FCurrent);
end;
if s <> '' then begin
if isExp then
nf := nfExp
else if isSci then
nf := nfSci
else if hasPerc then
nf := nfPercentage
else if hasThSep then
nf := nfFixedTh
else
nf := nfFixed;
end else
nf := nfGeneral;
FSections[FCurrSection].NumFormat := nf;
FSections[FCurrSection].FormatString := FSections[FCurrSection].FormatString + s;
end;
{ Scans a text in quotation marks. Tries to interpret the text as a currency
symbol (--> AnalyzeText) }
procedure TsNumFormatParser.ScanText;
var
token: Char;
done: Boolean;
s: String;
begin
done := false;
s := '';
while (FCurrent <= FEnd) and (FStatus = psOK) and not done do begin
token := FCurrent^;
if token = '"' then begin
done := true;
AnalyzeText(s);
end else begin
s := s + token;
inc(FCurrent);
end;
end;
FSections[FCurrSection].FormatString := Format('%s"%s"',
[FSections[FCurrSection].FormatString, s]);
end;
end.

View File

@ -538,6 +538,7 @@ type
function GetItem(AIndex: Integer): TsNumFormatData;
procedure SetItem(AIndex: Integer; AValue: TsNumFormatData);
protected
FWorkbook: TsWorkbook;
FFirstFormatIndexInFile: Integer;
FNextFormatIndex: Integer;
procedure AddBuiltinFormats; virtual;
@ -562,6 +563,7 @@ type
function FormatStringForWriting(AIndex: Integer): String; virtual;
procedure Sort;
property Workbook: TsWorkbook read FWorkbook;
property FirstFormatIndexInFile: Integer read FFirstFormatIndexInFile;
property Items[AIndex: Integer]: TsNumFormatData read GetItem write SetItem; default;
end;
@ -2938,6 +2940,7 @@ begin
inherited Create;
FWorkbook := AWorkbook;
CreateNumFormatList;
FNumFormatList.FWorkbook := AWorkbook;
end;
destructor TsCustomSpreadReader.Destroy;
@ -3008,6 +3011,7 @@ begin
inherited Create;
FWorkbook := AWorkbook;
CreateNumFormatList;
FNumFormatList.FWorkbook := AWorkbook;
end;
destructor TsCustomSpreadWriter.Destroy;

View File

@ -78,7 +78,9 @@ function SciFloat(AValue: Double; ADecimals: Byte): String;
//function TimeIntervalToString(AValue: TDateTime; AFormatStr: String): String;
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime): string;
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime): String; overload;
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime;
AFormatSettings: TFormatSettings): string; overload;
implementation
@ -1248,5 +1250,11 @@ begin
DateTimeToString(Result, FormatStr, DateTime, DefaultFormatSettings);
end;
function FormatDateTimeEx(const FormatStr: string; DateTime: TDateTime;
AFormatSettings: TFormatSettings): string;
begin
DateTimeToString(Result, FormatStr, DateTime, AFormatSettings);
end;
end.

View File

@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<Package Version="4">
<PathDelim Value="\"/>
@ -27,7 +27,7 @@
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Files Count="19">
<Files Count="20">
<Item1>
<Filename Value="fpolestorage.pas"/>
<UnitName Value="fpolestorage"/>
@ -104,6 +104,10 @@
<Filename Value="wikitable.pas"/>
<UnitName Value="wikitable"/>
</Item19>
<Item20>
<Filename Value="fpsnumformatparser.pas"/>
<UnitName Value="fpsNumFormatParser"/>
</Item20>
</Files>
<Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="2">
@ -122,5 +126,8 @@
<Version Value="2"/>
<IgnoreBinaries Value="False"/>
</PublishOptions>
<CustomOptions Items="ExternHelp" Version="2">
<_ExternHelp Items="Count"/>
</CustomOptions>
</Package>
</CONFIG>

View File

@ -8,12 +8,10 @@ interface
uses
fpolestorage, fpsallformats, fpsopendocument, fpspreadsheet, xlsbiff2,
xlsbiff5, xlsbiff8, xlsxooxml, fpsutils,
fpszipper,
uvirtuallayer_types,
xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, fpszipper, uvirtuallayer_types,
uvirtuallayer, uvirtuallayer_ole, uvirtuallayer_ole_helpers,
uvirtuallayer_ole_types, uvirtuallayer_stream, fpolebasic, xlscommon,
wikitable, LazarusPackageIntf;
wikitable, fpsNumFormatParser, LazarusPackageIntf;
implementation

View File

@ -0,0 +1,182 @@
unit numformatparsertests;
{$mode objfpc}{$H+}
interface
uses
// Not using Lazarus package as the user may be working with multiple versions
// Instead, add .. to unit search path
Classes, SysUtils, fpcunit, testutils, testregistry,
fpsallformats, fpspreadsheet, fpsnumformatparser, xlsbiff8
{and a project requirement for lclbase for utf8 handling},
testsutility;
type
TParserTestData = record
FormatString: String;
SollFormatString: String;
SollNumFormat: TsNumberFormat;
SollSectionCount: Integer;
SollDecimals: Byte;
SollCurrencySymbol: String;
end;
var
ParserTestData: Array[0..5] of TParserTestData;
procedure InitParserTestData;
type
TSpreadNumFormatParserTests = class(TTestCase)
private
protected
// Set up expected values:
procedure SetUp; override;
procedure TearDown; override;
// Reads numbers values from spreadsheet and checks against list
// One cell per test so some tests can fail and those further below may still work
published
procedure TestNumFormatParser;
end;
implementation
uses
TypInfo;
procedure InitParserTestData;
begin
// Tests with 1 format section only
with ParserTestData[0] do begin
FormatString := '0';
SollFormatString := '0';
SollNumFormat := nfFixed;
SollSectionCount := 1;
SollDecimals := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[1] do begin
FormatString := '0.000';
SollFormatString := '0.000';
SollNumFormat := nfFixed;
SollSectionCount := 1;
SollDecimals := 3;
SollCurrencySymbol := '';
end;
with ParserTestData[2] do begin
FormatString := '#,##0.000';
SollFormatString := '#,##0.000';
SollNumFormat := nfFixedTh;
SollSectionCount := 1;
SollDecimals := 3;
SollCurrencySymbol := '';
end;
with ParserTestData[3] do begin
FormatString := '0.000%';
SollFormatString := '0.000%';
SollNumFormat := nfPercentage;
SollSectionCount := 1;
SollDecimals := 3;
SollCurrencySymbol := '';
end;
with ParserTestData[4] do begin
FormatString := 'hh:mm:ss';
SollFormatString := 'hh:nn:ss';
SollNumFormat := nfLongTime;
SollSectionCount := 1;
SollDecimals := 0;
SollCurrencySymbol := '';
end;
with ParserTestData[5] do begin
FormatString := 'hh:mm:ss AM/PM';
SollFormatString := 'hh:nn:ss AM/PM';
SollNumFormat := nfLongTimeAM;
SollSectionCount := 1;
SollDecimals := 0;
SollCurrencySymbol := '';
end;
{
with ParserTestData[4] do begin
FormatString := '#,##0.00 "$";-#,##0.00 "$";0.00 "$"';
SollFormatString := '#,##0.00 "$";-#,##0.00 "$";0.00 "$"';
SollNumFormat := nfCurrency;
SollSectionCount := 3;
SollDecimals := 2;
SollCurrencySymbol := '$';
end;
with ParserTestData[5] do begin
FormatString := '#,##0.00 "$";-#,##0.00 "$";-';
SollFormatString := '#,##0.00 "$";-#,##0.00 "$";-';
SollNumFormat := nfCurrencyDash;
SollSectionCount := 3;
SollDecimals := 2;
SollCurrencySymbol := '$';
end; }
{
// This case will report a mismatching FormatString because of the [RED] --> ignore
with ParserTestData[6] do begin
FormatString := '#,##0.00 "$";[RED]-#,##0.00 "$";-';
SollFormatString := '#,##0.00 "$";-#,##0.00 "$";-';
SollNumFormat := nfCurrencyDashRed;
SollSectionCount := 3;
SollDecimals := 2;
SollCurrencySymbol := '$';
end;
}
end;
{ TSpreadNumFormatParserTests }
procedure TSpreadNumFormatParserTests.SetUp;
begin
inherited SetUp;
InitParserTestData;
end;
procedure TSpreadNumFormatParserTests.TearDown;
begin
inherited TearDown;
end;
procedure TSpreadNumFormatParserTests.TestNumFormatParser;
var
i: Integer;
parser: TsNumFormatParser;
MyWorkbook: TsWorkbook;
begin
MyWorkbook := TsWorkbook.Create; // needed to provide the FormatSettings for the parser
try
for i:=0 to 6 do begin
parser := TsNumFormatParser.Create(MyWorkbook, ParserTestData[i].FormatString);
try
CheckEquals(ParserTestData[i].SollFormatString, parser.FormatString,
'Test format string ' + ParserTestData[i].FormatString + ' construction mismatch');
CheckEquals(ord(ParserTestData[i].SollNumFormat), ord(parser.ParsedSections[0].NumFormat),
'Test format (' + GetEnumName(TypeInfo(TsNumberFormat), integer(ParserTestData[i].SollNumFormat)) +
') detection mismatch');
CheckEquals(ParserTestData[i].SollDecimals, parser.ParsedSections[0].Decimals,
'Test format (' + ParserTestData[i].FormatString + ') decimal detection mismatch');
CheckEquals(ParserTestData[i].SollCurrencySymbol, parser.ParsedSections[0].CurrencySymbol,
'Test format (' + ParserTestData[i].FormatString + ') currency symbol detection mismatch');
CheckEquals(ParserTestData[i].SollSectionCount, parser.ParsedSectionCount,
'Test format (' + ParserTestData[i].FormatString + ') section count mismatch');
finally
parser.Free;
end;
end;
finally
MyWorkbook.Free;
end;
end;
initialization
// Register so these tests are included in a full run
RegisterTest(TSpreadNumFormatParserTests);
InitParserTestData; //useful to have norm data if other code want to use this unit
end.
end.

View File

@ -78,7 +78,7 @@
<PackageName Value="FCL"/>
</Item4>
</RequiredPackages>
<Units Count="11">
<Units Count="12">
<Unit0>
<Filename Value="spreadtestgui.lpr"/>
<IsPartOfProject Value="True"/>
@ -134,6 +134,11 @@
<IsPartOfProject Value="True"/>
<UnitName Value="optiontests"/>
</Unit10>
<Unit11>
<Filename Value="numformatparsertests.pas"/>
<IsPartOfProject Value="True"/>
<UnitName Value="numformatparsertests"/>
</Unit11>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -5,7 +5,7 @@ program spreadtestgui;
uses
Interfaces, Forms, GuiTestRunner, datetests, stringtests, numberstests,
manualtests, testsutility, internaltests, formattests, colortests, fonttests,
optiontests;
optiontests, numformatparsertests;
begin
Application.Initialize;

View File

@ -480,7 +480,7 @@ type
implementation
uses
StrUtils;
StrUtils, fpsNumFormatParser;
function ConvertExcelDateTimeToDateTime(
const AExcelDateNum: Double; ADateMode: TDateMode): TDateTime;
@ -533,21 +533,6 @@ begin
end;
{ TsBIFFNumFormatParser } (*
constructor TsBIFFNumFormatParser.Create(AFormatString: String);
begin
inherited;
FFormatString := AFormatString;
Parse;
end;
procedure TsBIFFNumFormatParser.Parse;
begin
//
end;
*)
{ TsBIFFNumFormatList }
{ These are the built-in number formats as used by fpc. Before writing to file
@ -608,12 +593,29 @@ procedure TsBIFFNumFormatList.Analyze(AFormatIndex: Integer;
var AFormatString: String; var ANumFormat: TsNumberFormat;
var ADecimals: Byte; var ACurrencySymbol: String);
var
parser: TsNumFormatParser;
fmt: String;
begin
{
AFormatString := 'hh:mm AM/PM'; //"€" #,##.0;[red]"$" -#,##.000;-';
parser := TsNumFormatParser.Create(Workbook, AFormatString);
try
fmt := parser.FormatString;
ANumFormat := parser.ParsedSections[0].NumFormat;
ADecimals := parser.ParsedSections[0].Decimals;
ACurrencySymbol := parser.ParsedSections[0].CurrencySymbol;
finally
parser.Free;
end;
}
fmt := Lowercase(AFormatString);
{ Check the built-in formats first:
The prefix "[$-F400]" before the formatting string means that the system's
long Time format string is used. }
long time format string is used. }
if (pos('[$-F400]', AFormatString) = 1) then begin
ANumFormat := nfLongTime;
AFormatString := ''; // will be replaced by system's format setting