You've already forked lazarus-ccr
fpspreadsheet: Add text format. Allow leading apostrophe to prevent conversion of a cell text to numbers.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4538 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -946,6 +946,13 @@ object MainForm: TMainForm
|
||||
Hint = 'Time interval format'
|
||||
NumberFormat = nfTimeInterval
|
||||
end
|
||||
object AcNumFormatText: TsNumberFormatAction
|
||||
Category = 'FPSpreadsheet'
|
||||
WorkbookSource = WorkbookSource
|
||||
Caption = 'Text'
|
||||
Hint = 'Text format'
|
||||
NumberFormat = nfText
|
||||
end
|
||||
object AcFileOpen: TFileOpen
|
||||
Category = 'File'
|
||||
Caption = '&Open ...'
|
||||
@ -1018,6 +1025,51 @@ object MainForm: TMainForm
|
||||
Hint = 'Define currency symbols'
|
||||
OnExecute = AcSettingsCurrencyExecute
|
||||
end
|
||||
object AcSearch: TAction
|
||||
Category = 'Edit'
|
||||
Caption = 'Search...'
|
||||
Hint = 'Search for cells'
|
||||
ImageIndex = 70
|
||||
OnExecute = AcSearchExecute
|
||||
ShortCut = 16454
|
||||
end
|
||||
object AcShowGridLines: TAction
|
||||
Category = 'View'
|
||||
AutoCheck = True
|
||||
Caption = 'Grid lines'
|
||||
Checked = True
|
||||
OnExecute = AcShowGridLinesExecute
|
||||
OnUpdate = AcShowGridLinesUpdate
|
||||
end
|
||||
object AcShowHeaders: TAction
|
||||
Category = 'View'
|
||||
AutoCheck = True
|
||||
Caption = 'Show column/row headers'
|
||||
Checked = True
|
||||
OnExecute = AcShowHeadersExecute
|
||||
OnUpdate = AcShowHeadersUpdate
|
||||
end
|
||||
object AcFrozenRows: TAction
|
||||
Category = 'Worksheet'
|
||||
AutoCheck = True
|
||||
Caption = 'Frozen rows'
|
||||
OnExecute = AcFrozenRowsExecute
|
||||
OnUpdate = AcFrozenRowsUpdate
|
||||
end
|
||||
object AcFrozenCols: TAction
|
||||
Category = 'Worksheet'
|
||||
AutoCheck = True
|
||||
Caption = 'Frozen columns'
|
||||
OnExecute = AcFrozenColsExecute
|
||||
OnUpdate = AcFrozenColsUpdate
|
||||
end
|
||||
object AcWorksheetRTL: TAction
|
||||
Category = 'Worksheet'
|
||||
AutoCheck = True
|
||||
Caption = 'Text direction inverted'
|
||||
OnExecute = AcWorksheetRTLExecute
|
||||
OnUpdate = AcWorksheetRTLUpdate
|
||||
end
|
||||
object AcIncDecimals: TsDecimalsAction
|
||||
Category = 'FPSpreadsheet'
|
||||
WorkbookSource = WorkbookSource
|
||||
@ -1448,51 +1500,6 @@ object MainForm: TMainForm
|
||||
Hint = 'All vertical borders'
|
||||
ImageIndex = 43
|
||||
end
|
||||
object AcSearch: TAction
|
||||
Category = 'Edit'
|
||||
Caption = 'Search...'
|
||||
Hint = 'Search for cells'
|
||||
ImageIndex = 70
|
||||
OnExecute = AcSearchExecute
|
||||
ShortCut = 16454
|
||||
end
|
||||
object AcShowGridLines: TAction
|
||||
Category = 'View'
|
||||
AutoCheck = True
|
||||
Caption = 'Grid lines'
|
||||
Checked = True
|
||||
OnExecute = AcShowGridLinesExecute
|
||||
OnUpdate = AcShowGridLinesUpdate
|
||||
end
|
||||
object AcShowHeaders: TAction
|
||||
Category = 'View'
|
||||
AutoCheck = True
|
||||
Caption = 'Show column/row headers'
|
||||
Checked = True
|
||||
OnExecute = AcShowHeadersExecute
|
||||
OnUpdate = AcShowHeadersUpdate
|
||||
end
|
||||
object AcFrozenRows: TAction
|
||||
Category = 'Worksheet'
|
||||
AutoCheck = True
|
||||
Caption = 'Frozen rows'
|
||||
OnExecute = AcFrozenRowsExecute
|
||||
OnUpdate = AcFrozenRowsUpdate
|
||||
end
|
||||
object AcFrozenCols: TAction
|
||||
Category = 'Worksheet'
|
||||
AutoCheck = True
|
||||
Caption = 'Frozen columns'
|
||||
OnExecute = AcFrozenColsExecute
|
||||
OnUpdate = AcFrozenColsUpdate
|
||||
end
|
||||
object AcWorksheetRTL: TAction
|
||||
Category = 'Worksheet'
|
||||
AutoCheck = True
|
||||
Caption = 'Text direction inverted'
|
||||
OnExecute = AcWorksheetRTLExecute
|
||||
OnUpdate = AcWorksheetRTLUpdate
|
||||
end
|
||||
object AcCellBorderDiagUp: TsCellBorderAction
|
||||
Category = 'FPSpreadsheet'
|
||||
WorkbookSource = WorkbookSource
|
||||
@ -5302,6 +5309,13 @@ object MainForm: TMainForm
|
||||
Action = AcNumFormatTimeInterval
|
||||
AutoCheck = True
|
||||
end
|
||||
object MenuItem144: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object MenuItem145: TMenuItem
|
||||
Action = AcNumFormatText
|
||||
AutoCheck = True
|
||||
end
|
||||
end
|
||||
end
|
||||
object MnuView: TMenuItem
|
||||
|
@ -81,6 +81,8 @@ type
|
||||
MenuItem141: TMenuItem;
|
||||
MenuItem142: TMenuItem;
|
||||
MenuItem143: TMenuItem;
|
||||
MenuItem144: TMenuItem;
|
||||
MenuItem145: TMenuItem;
|
||||
MnuSettings: TMenuItem;
|
||||
MenuItem11: TMenuItem;
|
||||
MenuItem12: TMenuItem;
|
||||
@ -273,6 +275,7 @@ type
|
||||
AcNumFormatCustom: TsNumberFormatAction;
|
||||
AcCellBorderDiagUp: TsCellBorderAction;
|
||||
AcCellBorderDiagDown: TsCellBorderAction;
|
||||
AcNumFormatText: TsNumberFormatAction;
|
||||
Splitter2: TSplitter;
|
||||
Splitter3: TSplitter;
|
||||
ToolBar2: TToolBar;
|
||||
|
@ -8,7 +8,7 @@ object NumFormatForm: TNumFormatForm
|
||||
ClientHeight = 394
|
||||
ClientWidth = 559
|
||||
ShowHint = True
|
||||
LCLVersion = '1.5'
|
||||
LCLVersion = '1.7'
|
||||
object ButtonPanel1: TButtonPanel
|
||||
Left = 6
|
||||
Height = 34
|
||||
@ -67,6 +67,7 @@ object NumFormatForm: TNumFormatForm
|
||||
'Currency'
|
||||
'Date'
|
||||
'Time'
|
||||
'Text'
|
||||
)
|
||||
ItemHeight = 15
|
||||
OnClick = LbCategoryClick
|
||||
|
@ -11,7 +11,7 @@ uses
|
||||
|
||||
type
|
||||
TsNumFormatCategory = (nfcNumber, nfcPercent, nfcScientific, nfcFraction,
|
||||
nfcCurrency, nfcDate, nfcTime);
|
||||
nfcCurrency, nfcDate, nfcTime, nfcText);
|
||||
|
||||
{ TNumFormatForm }
|
||||
|
||||
@ -56,6 +56,7 @@ type
|
||||
{ private declarations }
|
||||
FWorkbook: TsWorkbook;
|
||||
FSampleValue: Double;
|
||||
FSampleText: String;
|
||||
FGenerator: array[TsNumFormatCategory] of Double;
|
||||
FNumFormatStrOfList: String;
|
||||
FLockCount: Integer;
|
||||
@ -74,7 +75,8 @@ type
|
||||
public
|
||||
{ public declarations }
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
procedure SetData(ANumFormatStr: String; AWorkbook: TsWorkbook; ASample: Double);
|
||||
procedure SetData(ANumFormatStr: String; AWorkbook: TsWorkbook;
|
||||
ASample: variant);
|
||||
property NumFormatStr: String read GetNumFormatStr;
|
||||
end;
|
||||
|
||||
@ -89,7 +91,7 @@ implementation
|
||||
{$R *.lfm}
|
||||
|
||||
uses
|
||||
LCLType, Math, DateUtils, TypInfo,
|
||||
LCLType, Math, DateUtils, TypInfo, variants,
|
||||
fpsUtils, fpsNumFormatParser, fpsCurrency,
|
||||
sCurrencyForm;
|
||||
|
||||
@ -244,6 +246,8 @@ begin
|
||||
AddToList(nfcTime, '[h]:nn');
|
||||
AddToList(nfcTime, '[h]:nn:ss');
|
||||
|
||||
AddToList(nfcText, '@');
|
||||
|
||||
// Add user-defined formats
|
||||
if copiedFormats <> nil then
|
||||
begin
|
||||
@ -351,6 +355,7 @@ begin
|
||||
FGenerator[nfcCurrency] := -1234.56789;
|
||||
FGenerator[nfcDate] := EncodeDate(YearOf(date), 1, 1);
|
||||
FGenerator[nfcTime] := EncodeTime(9, 0, 2, 235);
|
||||
FGenerator[nfcText] := NaN;
|
||||
GetRegisteredCurrencies(CbCurrSymbol.Items);
|
||||
end;
|
||||
|
||||
@ -419,44 +424,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
(*
|
||||
{ The global stringlist "NumFormats" contains to format string templates along
|
||||
with information on the category and of being built-in or user-defined. }
|
||||
procedure TNumFormatForm.BuildNumFormatLists(AWorkbook: TsWorkbook);
|
||||
var
|
||||
cat: TsNumFormatCategory;
|
||||
nfs: String;
|
||||
n, i: Integer;
|
||||
isUserDef: Boolean;
|
||||
copiedNumFormats: TStringList;
|
||||
begin
|
||||
copiedNumFormats := TStringList.Create;
|
||||
|
||||
for cat in TsNumFormatCategory do
|
||||
begin
|
||||
FreeAndNil(FNumFormatLists[cat]);
|
||||
FNumFormatLists[cat] := TsNumFormatList.Create(AWorkbook, true);
|
||||
end;
|
||||
|
||||
for i:=0 to NumFormats.Count-1 do
|
||||
begin
|
||||
nfs := NumFormats.Strings[i];
|
||||
n := PtrInt(NumFormats.Objects[i]);
|
||||
if n >= USER_OFFSET then
|
||||
begin
|
||||
isUserDef := true;
|
||||
// The category numbers of user-defined template items are offset by USER_OFFSET
|
||||
cat := TsNumFormatCategory(n - USER_OFFSET);
|
||||
end else
|
||||
begin
|
||||
isUserDef := false;
|
||||
// The category numbers of built-in template items are offset by BUILTIN_OFFSET
|
||||
cat := TsNumFormatCategory(n - BUILTIN_OFFSET);
|
||||
end;
|
||||
FNumFormatLists[cat].AddFormat(nfs);
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
|
||||
procedure TNumFormatForm.CbCurrSymbolSelect(Sender: TObject);
|
||||
begin
|
||||
@ -681,42 +648,29 @@ begin
|
||||
begin
|
||||
nfp := CreateNumFormatParams(NumFormats.Strings[i], FWorkbook.FormatSettings);
|
||||
try
|
||||
genValue := FGenerator[ACategory];
|
||||
if nfkTimeInterval in nfp.Sections[0].Kind then
|
||||
genvalue := genValue + 1.0;
|
||||
if ACategory = nfcFraction then
|
||||
if IsTextFormat(nfp) then
|
||||
s := 'abc'
|
||||
else
|
||||
begin
|
||||
digits := nfp.Sections[0].FracInt;
|
||||
numdigits := nfp.Sections[0].FracDenominator;
|
||||
genvalue := 1.0 / (IntPower(10, numdigits) - 3);
|
||||
if digits <> 0 then genvalue := -(1234 + genValue);
|
||||
genValue := FGenerator[ACategory];
|
||||
if nfkTimeInterval in nfp.Sections[0].Kind then
|
||||
genvalue := genValue + 1.0;
|
||||
if ACategory = nfcFraction then
|
||||
begin
|
||||
digits := nfp.Sections[0].FracInt;
|
||||
numdigits := nfp.Sections[0].FracDenominator;
|
||||
genvalue := 1.0 / (IntPower(10, numdigits) - 3);
|
||||
if digits <> 0 then genvalue := -(1234 + genValue);
|
||||
end;
|
||||
s := ConvertFloatToStr(genValue, nfp, FWorkbook.FormatSettings);
|
||||
if s = '' then s := 'General';
|
||||
end;
|
||||
s := ConvertFloatToStr(genValue, nfp, FWorkbook.FormatSettings);
|
||||
if s = '' then s := 'General';
|
||||
LbFormat.Items.AddObject(s, TObject(PtrInt(i)));
|
||||
finally
|
||||
nfp.Free;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{
|
||||
for i:=0 to FNumFormatLists[ACategory].Count-1 do
|
||||
begin
|
||||
nfp := FNumFormatLists[ACategory].Items[i];
|
||||
genvalue := FGenerator[ACategory];
|
||||
if nfkTimeInterval in nfp.Sections[0].Kind then
|
||||
genvalue := genValue + 1.0;
|
||||
if (ACategory = nfcFraction) then begin
|
||||
digits := nfp.Sections[0].FracInt;
|
||||
numdigits := nfp.Sections[0].FracDenominator;
|
||||
genvalue := 1 / (IntPower(10, numdigits) - 3);
|
||||
if digits <> 0 then genvalue := -(1234 + genValue);
|
||||
end;
|
||||
s := ConvertFloatToStr(genvalue, nfp, FWorkbook.FormatSettings);
|
||||
if s = '' then s := 'General';
|
||||
Add(s);
|
||||
end;
|
||||
}
|
||||
end;
|
||||
CurrSymbolPanel.Visible := (ACategory = nfcCurrency);
|
||||
GbOptions.Visible := not (ACategory in [nfcDate, nfcTime]);
|
||||
@ -742,7 +696,7 @@ begin
|
||||
end;
|
||||
|
||||
procedure TNumFormatForm.SetData(ANumFormatStr: String; AWorkbook: TsWorkbook;
|
||||
ASample: Double);
|
||||
ASample: variant);
|
||||
var
|
||||
cs: String;
|
||||
begin
|
||||
@ -752,7 +706,10 @@ begin
|
||||
cs := DefaultFormatSettings.CurrencyString;
|
||||
CbCurrSymbol.ItemIndex := CbCurrSymbol.Items.IndexOf(cs);
|
||||
|
||||
FSampleValue := ASample;
|
||||
if varIsStr(ASample) then
|
||||
FSampleText := VarToStr(ASample)
|
||||
else
|
||||
FSampleValue := ASample;
|
||||
InitNumFormats(FWorkbook.FormatSettings);
|
||||
SetNumFormatStr(ANumFormatStr);
|
||||
end;
|
||||
@ -852,8 +809,11 @@ begin
|
||||
else
|
||||
Sample.Font.Color := clWindowText;
|
||||
|
||||
Sample.Caption := ConvertFloatToStr(FSampleValue, ANumFormatParams,
|
||||
FWorkbook.FormatSettings);
|
||||
if IsTextFormat(ANumFormatParams) then
|
||||
Sample.Caption := ApplyTextFormat(FSampleText, ANumFormatParams)
|
||||
else
|
||||
Sample.Caption := ConvertFloatToStr(FSampleValue, ANumFormatParams,
|
||||
FWorkbook.FormatSettings);
|
||||
|
||||
BtnAddFormat.Enabled := (EdNumFormatStr.Text <> FNumFormatStrOfList);
|
||||
end;
|
||||
|
@ -1247,11 +1247,11 @@ procedure TsCellBorderAction.ApplyFormatToRange(ARange: TsCellRange);
|
||||
if Worksheet.IsMerged(cell) then
|
||||
begin
|
||||
Worksheet.FindMergedRange(cell, r1, c1, r2, c2);
|
||||
if (r1 >= AStart) and (r2 <= AEnd) then
|
||||
if (LongInt(r1) >= AStart) and (LongInt(r2) <= AEnd) then
|
||||
begin
|
||||
cell := Worksheet.GetCell(r1, c1);
|
||||
ShowBorder(ABorder, cell, ABorderStyle, AEnable);
|
||||
while (i <= r2) do begin
|
||||
while (i <= longint(r2)) do begin
|
||||
cell := GetWorksheet.GetCell(i, AColRow);
|
||||
inc(i);
|
||||
end;
|
||||
@ -1266,11 +1266,11 @@ procedure TsCellBorderAction.ApplyFormatToRange(ARange: TsCellRange);
|
||||
if Worksheet.IsMerged(cell) then
|
||||
begin
|
||||
Worksheet.FindMergedRange(cell, r1, c1, r2, c2);
|
||||
if (c1 >= AStart) and (c2 <= AEnd) then
|
||||
if (longInt(c1) >= AStart) and (LongInt(c2) <= AEnd) then
|
||||
begin
|
||||
cell := Worksheet.GetCell(r1, c1);
|
||||
ShowBorder(ABorder, cell, ABorderStyle, AEnable);
|
||||
while (i <= c2) do begin
|
||||
while (i <= longInt(c2)) do begin
|
||||
cell := GetWorksheet.GetCell(AColRow, i);
|
||||
inc(i);
|
||||
end;
|
||||
@ -1285,9 +1285,6 @@ procedure TsCellBorderAction.ApplyFormatToRange(ARange: TsCellRange);
|
||||
|
||||
var
|
||||
r, c: LongInt;
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
bs: TsCellBorderStyle;
|
||||
cell: PCell;
|
||||
begin
|
||||
// Top edge of range
|
||||
ShowBorders(cbNorth, ARange.Col1, ARange.Col2, ARange.Row1, false,
|
||||
|
@ -318,7 +318,7 @@ var
|
||||
begin
|
||||
Unused(AStream);
|
||||
Unused(ARow, ACol, AValue);
|
||||
s := FWorksheet.ReadAsUTF8Text(ACell);
|
||||
s := FWorksheet.ReadAsText(ACell);
|
||||
s := ConvertEncoding(s, EncodingUTF8, FEncoding);
|
||||
FCSVBuilder.AppendCell(s);
|
||||
end;
|
||||
@ -369,7 +369,7 @@ begin
|
||||
if CSVParams.NumberFormat <> '' then
|
||||
s := Format(CSVParams.NumberFormat, [AValue], FFormatSettings)
|
||||
else
|
||||
s := FWorksheet.ReadAsUTF8Text(ACell, FFormatSettings);
|
||||
s := FWorksheet.ReadAsText(ACell, FFormatSettings);
|
||||
s := ConvertEncoding(s, EncodingUTF8, FEncoding);
|
||||
FCSVBuilder.AppendCell(s);
|
||||
end;
|
||||
|
@ -1536,7 +1536,7 @@ var
|
||||
s: String;
|
||||
begin
|
||||
Unused(AValue, ACol, ARow);
|
||||
s := FWorksheet.ReadAsUTF8Text(ACell);
|
||||
s := FWorksheet.ReadAsText(ACell);
|
||||
AppendToStream(AStream,
|
||||
'<div>' + s + '</div>');
|
||||
end;
|
||||
@ -1547,7 +1547,7 @@ var
|
||||
s: String;
|
||||
begin
|
||||
Unused(AValue, ACol, ARow);
|
||||
s := FWOrksheet.ReadAsUTF8Text(ACell);
|
||||
s := FWOrksheet.ReadAsText(ACell);
|
||||
AppendToStream(AStream,
|
||||
'<div>' + s + '</div>');
|
||||
end;
|
||||
@ -1681,7 +1681,7 @@ var
|
||||
s: String;
|
||||
begin
|
||||
Unused(ARow, ACol, AValue);
|
||||
s := FWorksheet.ReadAsUTF8Text(ACell, FWorkbook.FormatSettings);
|
||||
s := FWorksheet.ReadAsText(ACell, FWorkbook.FormatSettings);
|
||||
AppendToStream(AStream,
|
||||
'<div>' + s + '</div>');
|
||||
end;
|
||||
|
@ -644,8 +644,6 @@ end;
|
||||
|
||||
{ Stores a font in the workbook's font list. Does not allow duplicates. }
|
||||
function TsHTMLAnalyzer.AddFont(AFont: TsFont): Integer;
|
||||
const
|
||||
EPS = 1e-3;
|
||||
var
|
||||
fnt: TsFont;
|
||||
begin
|
||||
|
@ -112,7 +112,7 @@ var
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
n := AStream.Read(hdr, SizeOf(hdr));
|
||||
n := AStream.Read(hdr{%H-}, SizeOf(hdr));
|
||||
if n < SizeOf(hdr) then exit;
|
||||
if hdr.dSignature <> $464D4520 then exit;
|
||||
|
||||
@ -297,7 +297,7 @@ var
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
n := AStream.Read(hdr, SizeOf(hdr));
|
||||
n := AStream.Read(hdr{%H-}, SizeOf(hdr));
|
||||
if n < SizeOf(hdr) then exit;
|
||||
if not (hdr.FileID in [$0A, $CD]) then exit;
|
||||
|
||||
@ -408,9 +408,6 @@ var
|
||||
function AnalyzeViewbox(AText: String; out w, h: Double): Boolean;
|
||||
var
|
||||
L: TStringList;
|
||||
val1, val2: Double;
|
||||
s: String;
|
||||
code: Integer;
|
||||
begin
|
||||
L := TStringList.Create;
|
||||
try
|
||||
@ -601,15 +598,13 @@ type
|
||||
Reserved: DWord; // Reserved (always 0)
|
||||
Checksum: Word; // Checksum value for previous 10 words
|
||||
end;
|
||||
const
|
||||
TWIPS = 20 * 72;
|
||||
var
|
||||
hdr: TWMFSpecialHeader;
|
||||
n: Int64;
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
n := AStream.Read(hdr, SizeOf(hdr));
|
||||
n := AStream.Read(hdr{%H-}, SizeOf(hdr));
|
||||
if n < SizeOf(hdr) then exit;
|
||||
if hdr.Key <> $9AC6CDD7 then exit;
|
||||
|
||||
|
@ -76,7 +76,8 @@ type
|
||||
nftEscaped, // '\'
|
||||
nftRepeat,
|
||||
nftEmptyCharWidth,
|
||||
nftTextFormat);
|
||||
nftTextFormat // '@'
|
||||
);
|
||||
|
||||
{@@ Element of the parsed number format sequence. Each element is identified
|
||||
by a token and has optional parameters stored as integer, float, and/or text. }
|
||||
@ -96,7 +97,8 @@ type
|
||||
|
||||
{@@ Summary information classifying a number format section }
|
||||
TsNumFormatKind = (nfkPercent, nfkExp, nfkCurrency, nfkFraction,
|
||||
nfkDate, nfkTime, nfkTimeInterval, nfkHasColor, nfkHasThSep, nfkHasFactor);
|
||||
nfkDate, nfkTime, nfkTimeInterval, nfkText,
|
||||
nfkHasColor, nfkHasThSep, nfkHasFactor);
|
||||
|
||||
{@@ Set of summary elements classifying and describing a number format section }
|
||||
TsNumFormatKinds = set of TsNumFormatKind;
|
||||
@ -208,6 +210,7 @@ function BuildNumberFormatString(ANumberFormat: TsNumberFormat;
|
||||
|
||||
function BuildFormatStringFromSection(const ASection: TsNumFormatSection): String;
|
||||
|
||||
function ApplyTextFormat(AText: String; AParams: TsNumFormatParams): String;
|
||||
function ConvertFloatToStr(AValue: Double; AParams: TsNumFormatParams;
|
||||
AFormatSettings: TFormatSettings): String;
|
||||
function CountDecs(AFormatString: String; ADecChars: TsDecsChars = ['0']): Byte;
|
||||
@ -239,6 +242,8 @@ function IsNumberValue(AText: String; AutoDetectNumberFormat: Boolean;
|
||||
|
||||
function IsTimeIntervalFormat(ANumFormat: TsNumFormatParams): Boolean;
|
||||
|
||||
function IsTextFormat(ANumFormat: TsNumFormatParams): Boolean;
|
||||
|
||||
function MakeLongDateFormat(ADateFormat: String): String;
|
||||
function MakeShortDateFormat(ADateFormat: String): String;
|
||||
procedure MakeTimeIntervalMask(Src: String; var Dest: String);
|
||||
@ -1259,6 +1264,8 @@ begin
|
||||
decs := DupeString('0', ADecimals);
|
||||
if ADecimals > 0 then decs := '.' + decs;
|
||||
case ANumberFormat of
|
||||
nfText:
|
||||
Result := '@';
|
||||
nfFixed:
|
||||
Result := '0' + decs;
|
||||
nfFixedTh:
|
||||
@ -1373,9 +1380,6 @@ begin
|
||||
nftEscaped:
|
||||
if element.TextValue <> '' then
|
||||
Result := Result + '\' + element.TextValue;
|
||||
nftTextFormat:
|
||||
if element.TextValue <> '' then
|
||||
Result := Result + element.TextValue;
|
||||
nftRepeat:
|
||||
if element.TextValue <> '' then Result := Result + '*' + element.TextValue;
|
||||
nftColor:
|
||||
@ -1390,6 +1394,8 @@ begin
|
||||
scCyan : Result := '[cyan]';
|
||||
else Result := Format('[Color%d]', [element.IntValue]);
|
||||
end;
|
||||
nftTextFormat:
|
||||
Result := '@';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
@ -1422,6 +1428,29 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Applies a text format to a text. The text placeholder is @. Supports
|
||||
appending and prepending text.
|
||||
-------------------------------------------------------------------------------}
|
||||
function ApplyTextFormat(AText: String; AParams: TsNumFormatParams): String;
|
||||
var
|
||||
sct: TsNumFormatSection;
|
||||
element: TsNumFormatElement;
|
||||
i, n: Integer;
|
||||
begin
|
||||
Result := '';
|
||||
for sct in AParams.Sections do
|
||||
for i := 0 to High(sct.Elements) do begin
|
||||
element := sct.Elements[i];
|
||||
case element.Token of
|
||||
nftTextFormat:
|
||||
Result := Result + AText;
|
||||
nftText:
|
||||
Result := Result + element.TextValue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Checks whether the specified text corresponds to a boolean value. For this,
|
||||
it must match the specified TRUE and FALSE text phrases.
|
||||
@ -1742,6 +1771,12 @@ begin
|
||||
(ANumFormat.Sections[0].Kind * [nfkTimeInterval] <> []);
|
||||
end;
|
||||
|
||||
function IsTextFormat(ANumFormat: TsNumFormatParams): Boolean;
|
||||
begin
|
||||
Result := (ANumFormat <> nil) and
|
||||
(ANumFormat.Sections[0].Kind = [nfkText]);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Creates a long date format string out of a short date format string.
|
||||
Retains the order of year-month-day and the separators, but uses 4 digits
|
||||
|
@ -25,6 +25,7 @@ const
|
||||
psErrMultipleExpChars = 11;
|
||||
psErrGeneralExpected = 12;
|
||||
psAmbiguousSymbol = 13;
|
||||
psErrNoValidTextFormat = 14;
|
||||
|
||||
type
|
||||
|
||||
@ -313,11 +314,11 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
|
||||
i := 0;
|
||||
isMonthMinute := false;
|
||||
|
||||
for el := 0 to High(section^.Elements) do
|
||||
begin
|
||||
case section^.Elements[el].Token of
|
||||
nftZeroDecs:
|
||||
section^.Decimals := section^.Elements[el].IntValue;
|
||||
@ -377,7 +378,10 @@ begin
|
||||
end;
|
||||
nftIntTh:
|
||||
section^.Kind := section^.Kind + [nfkHasThSep];
|
||||
nftTextFormat:
|
||||
section^.Kind := section^.Kind + [nfkText];
|
||||
end;
|
||||
end; // for
|
||||
|
||||
if FStatus <> psOK then
|
||||
exit;
|
||||
@ -389,6 +393,11 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (Length(FSections) = 1) and (section^.Kind = [nfkText]) then begin
|
||||
section^.NumFormat := nfText;
|
||||
exit;
|
||||
end;
|
||||
|
||||
section^.NumFormat := nfCustom;
|
||||
|
||||
if (section^.Kind * [nfkDate, nfkTime] <> []) or isMonthMinute then
|
||||
@ -450,78 +459,6 @@ begin
|
||||
if section^.Color = scRed then
|
||||
section^.NumFormat := nfCurrencyRed;
|
||||
end;
|
||||
|
||||
{
|
||||
el := 0;
|
||||
while el < Length(section^.Elements) do
|
||||
begin
|
||||
if IsNumberAt(ASection, el, nf, decs, next) then begin
|
||||
section^.Decimals := decs;
|
||||
if nf = nfFixedTh then begin
|
||||
if (nfkCurrency in section^.Kind) then
|
||||
section^.NumFormat := nfCurrency
|
||||
else
|
||||
section^.NumFormat := nfFixedTh
|
||||
end else
|
||||
begin
|
||||
section^.NumFormat := nf;
|
||||
if (nfkPercent in section^.Kind) then
|
||||
section^.NumFormat := nfPercentage
|
||||
else
|
||||
if (nfkExp in section^.Kind) then
|
||||
section^.NumFormat := nfExp
|
||||
else
|
||||
if (nfkCurrency in section^.Kind) then
|
||||
section^.NumFormat := nfCurrency
|
||||
else
|
||||
if (nfkFraction in section^.Kind) and (decs = 0) then begin
|
||||
f1 := section^.Elements[el].IntValue; // int part or numerator
|
||||
el := next;
|
||||
while IsTokenAt(nftSpace, ASection, el) or IsTextAt(' ', ASection, el) do
|
||||
inc(el);
|
||||
if IsTokenAt(nftFracSymbol, ASection, el) then begin
|
||||
inc(el);
|
||||
while IsTokenAt(nftSpace, ASection, el) or IsTextAt(' ', aSection, el) do
|
||||
inc(el);
|
||||
if IsNumberAt(ASection, el, nf, decs, next) and (nf in [nfFixed, nfFraction]) and (decs = 0) then
|
||||
begin
|
||||
section^.FracInt := 0;
|
||||
section^.FracNumerator := f1;
|
||||
section^.FracDenominator := section^.Elements[el].IntValue;
|
||||
section^.NumFormat := nfFraction;
|
||||
end;
|
||||
end else
|
||||
if IsNumberAt(ASection, el, nf, decs, next) and (nf in [nfFixed, nfFraction]) and (decs = 0) then
|
||||
begin
|
||||
f2 := section^.Elements[el].IntValue;
|
||||
el := next;
|
||||
while IsTokenAt(nftSpace, ASection, el) or IsTextAt(' ', ASection, el) do
|
||||
inc(el);
|
||||
if IsTokenAt(nftFracSymbol, ASection, el) then
|
||||
begin
|
||||
inc(el);
|
||||
while IsTokenAt(nftSpace, ASection, el) or IsTextAt(' ', ASection, el) do
|
||||
inc(el);
|
||||
if IsNumberAt(ASection, el, nf, decs, next) and (nf in [nfFixed, nfFraction]) and (decs=0) then
|
||||
begin
|
||||
section^.FracInt := f1;
|
||||
section^.FracNumerator := f2;
|
||||
section^.FracDenominator := section^.Elements[el].IntValue;
|
||||
section^.NumFormat := nfFraction;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
break;
|
||||
end else
|
||||
if IsTokenAt(nftColor, ASection, el) then
|
||||
section^.Color := section^.Elements[el].IntValue;
|
||||
inc(el);
|
||||
end;
|
||||
if (section^.NumFormat = nfCurrency) and (section^.Color = scRed) then
|
||||
section^.NumFormat := nfCurrencyRed;
|
||||
}
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -284,18 +284,18 @@ const
|
||||
SCHEMAS_XMLNS_TABLE = 'urn:oasis:names:tc:opendocument:xmlns:table:1.0';
|
||||
SCHEMAS_XMLNS_TEXT = 'urn:oasis:names:tc:opendocument:xmlns:text:1.0';
|
||||
SCHEMAS_XMLNS_V = 'urn:schemas-microsoft-com:vml';
|
||||
SCHEMAS_XMLNS_NUMBER = 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0';
|
||||
SCHEMAS_XMLNS_CHART = 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0';
|
||||
SCHEMAS_XMLNS_DR3D = 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0';
|
||||
SCHEMAS_XMLNS_MATH = 'http://www.w3.org/1998/Math/MathML';
|
||||
SCHEMAS_XMLNS_FORM = 'urn:oasis:names:tc:opendocument:xmlns:form:1.0';
|
||||
SCHEMAS_XMLNS_SCRIPT = 'urn:oasis:names:tc:opendocument:xmlns:script:1.0';
|
||||
SCHEMAS_XMLNS_OOOW = 'http://openoffice.org/2004/writer';
|
||||
SCHEMAS_XMLNS_OOOC = 'http://openoffice.org/2004/calc';
|
||||
SCHEMAS_XMLNS_DOM = 'http://www.w3.org/2001/xml-events';
|
||||
SCHEMAS_XMLNS_XFORMS = 'http://www.w3.org/2002/xforms';
|
||||
SCHEMAS_XMLNS_XSD = 'http://www.w3.org/2001/XMLSchema';
|
||||
SCHEMAS_XMLNS_XSI = 'http://www.w3.org/2001/XMLSchema-instance';
|
||||
{%H-}SCHEMAS_XMLNS_NUMBER = 'urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0';
|
||||
{%H-}SCHEMAS_XMLNS_CHART = 'urn:oasis:names:tc:opendocument:xmlns:chart:1.0';
|
||||
{%H-}SCHEMAS_XMLNS_DR3D = 'urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0';
|
||||
{%H-}SCHEMAS_XMLNS_MATH = 'http://www.w3.org/1998/Math/MathML';
|
||||
{%H-}SCHEMAS_XMLNS_FORM = 'urn:oasis:names:tc:opendocument:xmlns:form:1.0';
|
||||
{%H-}SCHEMAS_XMLNS_SCRIPT = 'urn:oasis:names:tc:opendocument:xmlns:script:1.0';
|
||||
{%H-}SCHEMAS_XMLNS_OOOW = 'http://openoffice.org/2004/writer';
|
||||
{%H-}SCHEMAS_XMLNS_OOOC = 'http://openoffice.org/2004/calc';
|
||||
{%H-}SCHEMAS_XMLNS_DOM = 'http://www.w3.org/2001/xml-events';
|
||||
{%H-}SCHEMAS_XMLNS_XFORMS = 'http://www.w3.org/2002/xforms';
|
||||
{%H-}SCHEMAS_XMLNS_XSD = 'http://www.w3.org/2001/XMLSchema';
|
||||
{%H-}SCHEMAS_XMLNS_XSI = 'http://www.w3.org/2001/XMLSchema-instance';
|
||||
|
||||
{ DATEMODE similar to but not the same as XLS format; used in time only values. }
|
||||
DATEMODE_1899_BASE=0; //apparently 1899-12-30 for ODF in FPC DateTime;
|
||||
@ -4562,15 +4562,15 @@ var
|
||||
styleName: String;
|
||||
colsRepeated: Integer;
|
||||
colsRepeatedStr: String;
|
||||
firstRepeatedPrintCol, lastRepeatedPrintCol: Cardinal;
|
||||
firstRepeatedPrintCol, lastRepeatedPrintCol: Longint;
|
||||
headerCols: Boolean;
|
||||
begin
|
||||
widthMultiplier := Workbook.GetFont(0).Size / 2;
|
||||
lastCol := ASheet.GetLastColIndex;
|
||||
firstRepeatedPrintCol := ASheet.PageLayout.RepeatedCols.FirstIndex;
|
||||
lastRepeatedPrintCol := ASheet.PageLayout.RepeatedCols.LastIndex;
|
||||
if (firstRepeatedPrintCol <> UNASSIGNED_ROW_COL_INDEX) and
|
||||
(lastRepeatedPrintCol = UNASSIGNED_ROW_COL_INDEX)
|
||||
if (firstRepeatedPrintCol <> Longint(UNASSIGNED_ROW_COL_INDEX)) and
|
||||
(lastRepeatedPrintCol = LongInt(UNASSIGNED_ROW_COL_INDEX))
|
||||
then
|
||||
lastRepeatedPrintCol := firstRepeatedPrintCol;
|
||||
|
||||
@ -5747,12 +5747,10 @@ function TsSpreadOpenDocWriter.WritePrintRangesAsXMLString(ASheet: TsWorksheet):
|
||||
var
|
||||
i: Integer;
|
||||
rng: TsCellRange;
|
||||
srng: String;
|
||||
sheetName: String;
|
||||
begin
|
||||
if ASheet.PageLayout.NumPrintRanges > 0 then
|
||||
begin
|
||||
srng := '';
|
||||
for i := 0 to ASheet.PageLayout.NumPrintRanges - 1 do
|
||||
begin
|
||||
rng := ASheet.PageLayout.PrintRange[i];
|
||||
@ -6457,7 +6455,7 @@ begin
|
||||
DisplayStr := '1.#INF';
|
||||
end else begin
|
||||
StrValue := FloatToStr(AValue, FPointSeparatorSettings); // Uses '.' as decimal separator
|
||||
DisplayStr := FWorksheet.ReadAsUTF8Text(ACell); //FloatToStr(AValue); // Uses locale decimal separator
|
||||
DisplayStr := FWorksheet.ReadAsText(ACell); //FloatToStr(AValue); // Uses locale decimal separator
|
||||
end;
|
||||
|
||||
// Hyperlink
|
||||
@ -6530,7 +6528,7 @@ begin
|
||||
DecodeTime(AValue, h,m,s,ms);
|
||||
strValue := Format('PT%.2dH%.2dM%.2d.%.3dS', [trunc(AValue)*24+h, m, s, ms], FPointSeparatorSettings);
|
||||
// strValue := FormatDateTime(ISO8601FormatHoursOverflow, AValue, [fdoInterval]);
|
||||
displayStr := FWorksheet.ReadAsUTF8Text(ACell);
|
||||
displayStr := FWorksheet.ReadAsText(ACell);
|
||||
// displayStr := FormatDateTime(fmt.NumberFormatStr, AValue, [fdoInterval]);
|
||||
AppendToStream(AStream, Format(
|
||||
'<table:table-cell office:value-type="time" office:time-value="%s" %s %s>' +
|
||||
@ -6548,7 +6546,7 @@ begin
|
||||
else
|
||||
isTimeOnly := false;
|
||||
strValue := FormatDateTime(DATE_FMT[isTimeOnly], AValue);
|
||||
displayStr := FWorksheet.ReadAsUTF8Text(ACell);
|
||||
displayStr := FWorksheet.ReadAsText(ACell);
|
||||
AppendToStream(AStream, Format(
|
||||
'<table:table-cell office:value-type="%s" office:%s-value="%s" %s %s>' +
|
||||
comment +
|
||||
|
@ -1122,7 +1122,7 @@ begin
|
||||
rtInteger : WriteNumber(ACell, res.ResInteger);
|
||||
rtFloat : WriteNumber(ACell, res.ResFloat);
|
||||
rtDateTime : WriteDateTime(ACell, res.ResDateTime);
|
||||
rtString : WriteUTF8Text(ACell, res.ResString);
|
||||
rtString : WriteText(ACell, res.ResString);
|
||||
rtHyperlink : begin
|
||||
link := ArgToString(res);
|
||||
p := pos(HYPERLINK_SEPARATOR, link);
|
||||
@ -1133,7 +1133,7 @@ begin
|
||||
end else
|
||||
txt := link;
|
||||
WriteHyperlink(ACell, link);
|
||||
WriteUTF8Text(ACell, txt);
|
||||
WriteText(ACell, txt);
|
||||
end;
|
||||
rtBoolean : WriteBoolValue(ACell, res.ResBoolean);
|
||||
rtCell : begin
|
||||
@ -1141,7 +1141,7 @@ begin
|
||||
case cell^.ContentType of
|
||||
cctNumber : WriteNumber(ACell, cell^.NumberValue);
|
||||
cctDateTime : WriteDateTime(ACell, cell^.DateTimeValue);
|
||||
cctUTF8String: WriteUTF8Text(ACell, cell^.UTF8StringValue);
|
||||
cctUTF8String: WriteText(ACell, cell^.UTF8StringValue);
|
||||
cctBool : WriteBoolValue(ACell, cell^.Boolvalue);
|
||||
cctError : WriteErrorValue(ACell, cell^.ErrorValue);
|
||||
cctEmpty : WriteBlank(ACell);
|
||||
@ -2939,17 +2939,12 @@ end;
|
||||
function TsWorksheet.ReadCellBorderStyles(ACell: PCell): TsCellBorderStyles;
|
||||
var
|
||||
fmt: PsCellFormat;
|
||||
b: TsCellBorder;
|
||||
begin
|
||||
Result := DEFAULT_BORDERSTYLES;
|
||||
if ACell <> nil then
|
||||
begin
|
||||
fmt := Workbook.GetPointerToCellFormat(ACell^.FormatIndex);
|
||||
Result := Fmt^.BorderStyles;
|
||||
{
|
||||
for b in fmt^.Border do
|
||||
Result[b] := fmt^.BorderStyles[b];
|
||||
}
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -3446,7 +3441,7 @@ begin
|
||||
img^.Index := Workbook.AddEmbeddedStream(AFileName);
|
||||
Workbook.GetEmbeddedStream(img^.Index).LoadFromFile(AFileName);
|
||||
end;
|
||||
FImages.Add(img);
|
||||
Result := FImages.Add(img);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@ -4283,7 +4278,7 @@ begin
|
||||
if ACell <> nil then begin
|
||||
ACell^.FormulaValue := '';
|
||||
if HasHyperlink(ACell) then
|
||||
WriteUTF8Text(ACell, '') // '' will be replaced by the hyperlink target.
|
||||
WriteText(ACell, '') // '' will be replaced by the hyperlink target.
|
||||
else
|
||||
begin
|
||||
ACell^.ContentType := cctEmpty;
|
||||
@ -4365,23 +4360,42 @@ begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
|
||||
fmt := Workbook.GetCellFormat(ACell^.FormatIndex);
|
||||
numFmtParams := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||
ACell^.FormulaValue := '';
|
||||
|
||||
if AValue = '' then
|
||||
begin
|
||||
WriteUTF8Text(ACell, '');
|
||||
WriteText(ACell, '');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// Force text format by putting an apostrophe at the text beginning
|
||||
if AValue[1] = '''' then
|
||||
begin
|
||||
Delete(AValue, 1, 1);
|
||||
WriteNumberFormat(ACell, nfText);
|
||||
end;
|
||||
|
||||
fmt := Workbook.GetCellFormat(ACell^.FormatIndex);
|
||||
numFmtParams := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||
|
||||
isPercent := Pos('%', AValue) = Length(AValue);
|
||||
if isPercent then Delete(AValue, Length(AValue), 1);
|
||||
|
||||
ACell^.FormulaValue := '';
|
||||
{
|
||||
if IsTextFormat(numFmtParams) then
|
||||
begin
|
||||
WriteText(ACell, AValue);
|
||||
exit;
|
||||
end;
|
||||
}
|
||||
|
||||
if TryStrToCurrency(AValue, number, currSym, FWorkbook.FormatSettings) then
|
||||
begin
|
||||
WriteCurrency(ACell, number, nfCurrencyRed, -1, currSym);
|
||||
if IsTextFormat(numFmtParams) then begin
|
||||
WriteNumberFormat(ACell, nfText);
|
||||
WriteText(ACell, AValue);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
@ -4389,6 +4403,11 @@ begin
|
||||
begin
|
||||
WriteNumber(ACell, number);
|
||||
WriteFractionFormat(ACell, ismixed, maxdig, maxdig);
|
||||
if IsTextFormat(numFmtParams) then
|
||||
begin
|
||||
WriteNumberFormat(ACell, nfText);
|
||||
WriteText(ACell, AValue);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
@ -4403,6 +4422,11 @@ begin
|
||||
else
|
||||
WriteNumber(ACell, number);
|
||||
end;
|
||||
if IsTextFormat(numFmtParams) then
|
||||
begin
|
||||
WriteNumberFormat(ACell, nfText);
|
||||
WriteText(ACell, AValue);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
@ -4420,18 +4444,23 @@ begin
|
||||
end else
|
||||
if frac(number) = 0.0 then // this is a date alone
|
||||
begin
|
||||
if not IsDateFormat(numFmtParams) then
|
||||
// if not IsDateFormat(numFmtParams) then
|
||||
WriteDateTime(ACell, number, nfShortDate);
|
||||
end else
|
||||
if not IsDateTimeFormat(fmt.NumberFormat) then
|
||||
WriteDateTime(ACell, number, nfShortDateTime)
|
||||
else
|
||||
WriteDateTime(ACell, number);
|
||||
if IsTextFormat(numFmtParams) then
|
||||
begin
|
||||
WriteNumberFormat(ACell, nfText);
|
||||
WriteText(ACell, AValue);
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
|
||||
HTMLToRichText(FWorkbook, ReadcellFont(ACell), AValue, plain, rtParams);
|
||||
WriteUTF8Text(ACell, plain, rtParams);
|
||||
WriteText(ACell, plain, rtParams);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
@ -4754,6 +4783,9 @@ procedure TsWorksheet.WriteDateTimeFormat(ACell: PCell;
|
||||
var
|
||||
fmt: TsCellFormat;
|
||||
nfs: String;
|
||||
nfp: TsNumFormatParams;
|
||||
isTextFmt, wasTextFmt: Boolean;
|
||||
oldVal: String;
|
||||
begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
@ -4761,15 +4793,22 @@ begin
|
||||
if not ((ANumFormat in [nfGeneral, nfCustom]) or IsDateTimeFormat(ANumFormat)) then
|
||||
raise Exception.Create('WriteDateTimeFormat can only be called with date/time formats.');
|
||||
|
||||
isTextFmt := false;
|
||||
wasTextFmt := false;
|
||||
|
||||
fmt := FWorkbook.GetCellFormat(ACell^.FormatIndex);
|
||||
fmt.NumberFormat := ANumFormat;
|
||||
if (ANumFormat <> nfGeneral) then
|
||||
begin
|
||||
nfp := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||
wasTextFmt := IsTextFormat(nfp);
|
||||
oldval := ReadAsText(ACell);
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
if (ANumFormatString = '') then
|
||||
nfs := BuildDateTimeFormatString(ANumFormat, Workbook.FormatSettings)
|
||||
else
|
||||
nfs := ANumFormatString;
|
||||
isTextFmt := (nfs = '@');
|
||||
end else
|
||||
begin
|
||||
Exclude(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
@ -4780,6 +4819,12 @@ begin
|
||||
fmt.NumberFormatIndex := Workbook.AddNumberFormat(nfs);
|
||||
ACell^.FormatIndex := FWorkbook.AddCellFormat(fmt);
|
||||
|
||||
if isTextFmt then
|
||||
WriteText(ACell, oldval)
|
||||
else
|
||||
if wasTextFmt then
|
||||
WriteCellValueAsString(ACell, ACell^.UTF8StringValue);
|
||||
|
||||
ChangedCell(ACell^.Row, ACell^.Col);
|
||||
end;
|
||||
|
||||
@ -4968,13 +5013,19 @@ procedure TsWorksheet.WriteNumberFormat(ACell: PCell;
|
||||
var
|
||||
fmt: TsCellFormat;
|
||||
fmtStr: String;
|
||||
nfp: TsNumFormatParams;
|
||||
wasTextFmt: Boolean;
|
||||
begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
|
||||
wasTextFmt := false;
|
||||
|
||||
fmt := Workbook.GetCellFormat(ACell^.FormatIndex);
|
||||
fmt.NumberFormat := ANumFormat;
|
||||
if ANumFormat <> nfGeneral then begin
|
||||
nfp := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||
wasTextFmt := IsTextFormat(nfp);
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
if IsCurrencyFormat(ANumFormat) then
|
||||
begin
|
||||
@ -4991,6 +5042,9 @@ begin
|
||||
end;
|
||||
ACell^.FormatIndex := Workbook.AddCellFormat(fmt);
|
||||
|
||||
if wasTextFmt then
|
||||
WriteCellValueAsString(ACell, ACell^.UTF8StringValue);
|
||||
|
||||
ChangedCell(ACell^.Row, ACell^.Col);
|
||||
end;
|
||||
|
||||
@ -5077,17 +5131,28 @@ procedure TsWorksheet.WriteNumberFormat(ACell: PCell;
|
||||
var
|
||||
fmt: TsCellFormat;
|
||||
fmtStr: String;
|
||||
nfp: TsNumFormatParams;
|
||||
oldval: String;
|
||||
isTextFmt, wasTextFmt: Boolean;
|
||||
begin
|
||||
if ACell = nil then
|
||||
exit;
|
||||
|
||||
isTextFmt := false;
|
||||
wasTextFmt := false;
|
||||
|
||||
fmt := Workbook.GetCellFormat(ACell^.FormatIndex);
|
||||
|
||||
if ANumFormat <> nfGeneral then begin
|
||||
nfp := Workbook.GetNumberFormat(fmt.NumberFormatIndex);
|
||||
wasTextFmt := IsTextFormat(nfp);
|
||||
oldval := ReadAsText(ACell);
|
||||
Include(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
if (ANumFormatString = '') then
|
||||
fmtStr := BuildNumberFormatString(ANumFormat, Workbook.FormatSettings)
|
||||
else
|
||||
fmtStr := ANumFormatString;
|
||||
isTextFmt := (fmtstr = '@');
|
||||
fmt.NumberFormatIndex := Workbook.AddNumberFormat(fmtStr);
|
||||
end else begin
|
||||
Exclude(fmt.UsedFormattingFields, uffNumberFormat);
|
||||
@ -5095,6 +5160,12 @@ begin
|
||||
end;
|
||||
ACell^.FormatIndex := Workbook.AddCellFormat(fmt);
|
||||
|
||||
if isTextFmt then
|
||||
WriteText(ACell, oldval)
|
||||
else
|
||||
if wasTextFmt then
|
||||
WriteCellValueAsString(ACell, ACell^.UTF8StringValue);
|
||||
|
||||
ChangedCell(ACell^.Row, ACell^.Col);
|
||||
end;
|
||||
|
||||
@ -8131,10 +8202,11 @@ var
|
||||
r, c: LongInt;
|
||||
dr, dc: LongInt;
|
||||
srcCell, destCell: PCell;
|
||||
i: Integer; // counter
|
||||
ncs, nrs, ncd, nrd: Integer; // Num cols source, num rows source, ...
|
||||
rdest, cdest: Integer; // row and column index at destination
|
||||
nselS, nselD: Integer; // count of selected blocks
|
||||
i: Integer; // counter
|
||||
ncs, nrs: Integer; // Num cols source, num rows source, ...
|
||||
ncd, nrd: Integer;
|
||||
rdest, cdest: Integer; // row and column index at destination
|
||||
nselS, nselD: Integer; // count of selected blocks
|
||||
begin
|
||||
if AStream = nil then
|
||||
exit;
|
||||
@ -8224,25 +8296,25 @@ begin
|
||||
// Iterate over all destination blocks
|
||||
for i := 0 to nselD-1 do
|
||||
begin
|
||||
// size of current selected block at destination
|
||||
// size of currently selected block at destination
|
||||
with ActiveWorksheet.GetSelection[i] do
|
||||
begin
|
||||
ncd := LongInt(Col2) - LongInt(Col1) + 1;
|
||||
nrd := LongInt(Row2) - LongInt(Row1) + 1;
|
||||
ncd := Integer(Col2) - Integer(Col1) + 1;
|
||||
nrd := Integer(Row2) - Integer(Row1) + 1;
|
||||
end;
|
||||
r := ActiveWorksheet.GetSelection[i].Row1;
|
||||
while r <= ActiveWorksheet.GetSelection[i].Row2 do begin
|
||||
while r <= longint(ActiveWorksheet.GetSelection[i].Row2) do begin
|
||||
c := ActiveWorksheet.GetSelection[i].Col1;
|
||||
while c <= ActiveWorksheet.GetSelection[i].Col2 do begin
|
||||
while c <= longint(ActiveWorksheet.GetSelection[i].Col2) do begin
|
||||
dr := r - clipsheet.GetFirstRowIndex;
|
||||
dc := c - clipsheet.GetFirstColIndex;
|
||||
for srccell in clipsheet.Cells do
|
||||
begin
|
||||
rdest := srccell^.Row + dr;
|
||||
if rdest > ActiveWorksheet.GetSelection[i].Row2 then
|
||||
rdest := longint(srccell^.Row) + dr;
|
||||
if rdest > integer(ActiveWorksheet.GetSelection[i].Row2) then
|
||||
Continue;
|
||||
cdest := srcCell^.Col + dc;
|
||||
if cdest > ActiveWorksheet.GetSelection[i].Col2 then
|
||||
cdest := longint(srcCell^.Col) + dc;
|
||||
if cdest > integer(ActiveWorksheet.GetSelection[i].Col2) then
|
||||
Continue;
|
||||
destcell := ActiveWorksheet.GetCell(
|
||||
LongInt(srcCell^.Row) + dr,
|
||||
|
@ -44,7 +44,7 @@ type
|
||||
|
||||
TsSelPen = class(TPen)
|
||||
public
|
||||
constructor Create;
|
||||
constructor Create; override;
|
||||
published
|
||||
property Width stored true default 3;
|
||||
property JoinStyle default pjsMiter;
|
||||
@ -1544,7 +1544,6 @@ var
|
||||
r1, c1, r2, c2: Cardinal;
|
||||
cell: PCell;
|
||||
Rct: TRect;
|
||||
s: String;
|
||||
delta: Integer;
|
||||
begin
|
||||
inherited;
|
||||
@ -1553,7 +1552,6 @@ begin
|
||||
delta := FSelPen.Width div 2;
|
||||
cell := Worksheet.FindCell(GetWorksheetRow(Row), GetWorksheetCol(Col));
|
||||
if Worksheet.IsMerged(cell) then begin
|
||||
s := Editor.ClassName;
|
||||
Worksheet.FindMergedRange(cell, r1,c1,r2,c2);
|
||||
Rct := CellRect(GetGridCol(c1), GetGridRow(r1), GetGridCol(c2), GetGridRow(r2));
|
||||
end else
|
||||
@ -1833,63 +1831,17 @@ const
|
||||
2, 1, 2, 1, 2,
|
||||
2);
|
||||
var
|
||||
width3: Boolean; // line is 3 pixels wide
|
||||
deltax, deltay: Integer;
|
||||
angle: Double;
|
||||
savedCosmetic: Boolean;
|
||||
begin
|
||||
savedCosmetic := Canvas.Pen.Cosmetic;
|
||||
width3 := (ABorderStyle.LineStyle in [lsThick, lsDouble]);
|
||||
|
||||
Canvas.Pen.Style := PEN_STYLES[ABorderStyle.LineStyle];
|
||||
Canvas.Pen.Width := PEN_WIDTHS[ABorderStyle.LineStyle];
|
||||
Canvas.Pen.Color := ABorderStyle.Color and $00FFFFFF;
|
||||
Canvas.Pen.EndCap := pecSquare;
|
||||
if ABorderStyle.LineStyle = lsHair then
|
||||
Canvas.Pen.Cosmetic := false;
|
||||
(*
|
||||
// Workaround until efficient drawing procedures for diagonal "hair" lines
|
||||
// is available
|
||||
{
|
||||
if (ADrawDirection in [drawDiagUp, drawDiagDown]) and
|
||||
(ABorderStyle.LineStyle = lsHair)
|
||||
then
|
||||
ABorderStyle.LineStyle := lsDotted;
|
||||
}
|
||||
|
||||
// Tuning the rectangle to avoid issues at the grid borders and to get nice corners
|
||||
if (ABorderStyle.LineStyle in [lsMedium, lsMediumDash, lsMediumDashDot,
|
||||
lsMediumDashDotDot, lsSlantDashDot, lsThick, lsDouble]) then
|
||||
begin
|
||||
{
|
||||
if ACol = ColCount-1 then
|
||||
begin
|
||||
if (ADrawDirection = drawVert) and (ACoord = ARect.Right-1) and width3
|
||||
then dec(ACoord);
|
||||
dec(ARect.Right);
|
||||
end;
|
||||
if ARow = RowCount-1 then
|
||||
begin
|
||||
if (ADrawDirection = drawHor) and (ACoord = ARect.Bottom-1) and width3
|
||||
then dec(ACoord);
|
||||
dec(ARect.Bottom);
|
||||
end;
|
||||
}
|
||||
end;
|
||||
if ABorderStyle.LineStyle in [lsMedium, lsMediumDash, lsMediumDashDot,
|
||||
lsMediumDashDotDot, lsSlantDashDot, lsThick, lsHair] then
|
||||
begin
|
||||
if (ADrawDirection = drawHor) then
|
||||
dec(ARect.Right, 1)
|
||||
else if (ADrawDirection = drawVert) then
|
||||
dec(ARect.Bottom, 1)
|
||||
else if (ADrawDirection in [drawDiagUp, drawDiagDown]) then
|
||||
begin
|
||||
dec(ARect.Right, 1);
|
||||
dec(ARect.Bottom, 2);
|
||||
end;
|
||||
end;
|
||||
*)
|
||||
// Painting
|
||||
case ABorderStyle.LineStyle of
|
||||
lsThin, lsMedium, lsThick, lsDotted, lsDashed, lsDashDot, lsDashDotDot,
|
||||
@ -2914,7 +2866,6 @@ function TsCustomWorksheetGrid.GetCellBorderStyle(ACol, ARow: Integer;
|
||||
ABorder: TsCellBorder): TsCellBorderStyle;
|
||||
var
|
||||
cell: PCell;
|
||||
base: PCell;
|
||||
begin
|
||||
Result := DEFAULT_BORDERSTYLES[ABorder];
|
||||
if Assigned(Worksheet) then
|
||||
@ -3320,10 +3271,10 @@ begin
|
||||
|
||||
r := GetWorksheetRow(ARow);
|
||||
c := GetWorksheetCol(ACol);
|
||||
if (r + ADeltaRow < 0) or (c + ADeltaCol < 0) then
|
||||
if (longint(r) + ADeltaRow < 0) or (longint(c) + ADeltaCol < 0) then
|
||||
neighborcell := nil
|
||||
else
|
||||
neighborcell := Worksheet.FindCell(r + ADeltaRow, c + ADeltaCol);
|
||||
neighborcell := Worksheet.FindCell(longint(r) + ADeltaRow, longint(c) + ADeltaCol);
|
||||
|
||||
// Only cell has border, but neighbor has not
|
||||
if HasBorder(ACell, border) and not HasBorder(neighborCell, neighborBorder) then
|
||||
@ -3474,7 +3425,7 @@ procedure TsCustomWorksheetGrid.HeaderSizing(const IsColumn:boolean;
|
||||
const AIndex,ASize:Integer);
|
||||
var
|
||||
gc, gr: Integer;
|
||||
sc, sr, sr1, sr2, sc1, sc2, si: Cardinal;
|
||||
sr1, sr2, sc1, sc2, si: Cardinal;
|
||||
cell: PCell;
|
||||
begin
|
||||
inherited;
|
||||
@ -3486,10 +3437,8 @@ begin
|
||||
si := IfThen(IsColumn, GetWorksheetCol(AIndex), GetWorksheetRow(AIndex));
|
||||
for gc := GetFirstVisibleColumn to GetLastVisibleColumn do
|
||||
begin
|
||||
sc := GetWorksheetCol(gc);
|
||||
for gr := GetFirstVisibleRow to GetLastVisibleRow do
|
||||
begin
|
||||
sr := GetWorksheetRow(gr);
|
||||
cell := Worksheet.FindCell(gr, gc);
|
||||
if Worksheet.IsMerged(cell) then begin
|
||||
Worksheet.FindMergedRange(cell, sr1, sc1, sr2, sc2);
|
||||
|
@ -546,6 +546,8 @@ type
|
||||
// dates and times
|
||||
nfShortDateTime, nfShortDate, nfLongDate, nfShortTime, nfLongTime,
|
||||
nfShortTimeAM, nfLongTimeAM, nfDayMonth, nfMonthYear, nfTimeInterval,
|
||||
// text
|
||||
nfText,
|
||||
// other (format string goes directly into the file)
|
||||
nfCustom);
|
||||
|
||||
|
@ -2187,8 +2187,6 @@ end;
|
||||
@param AFont2 Pointer to the second font to be compared
|
||||
-------------------------------------------------------------------------------}
|
||||
function SameFont(AFont1, AFont2: TsFont): Boolean;
|
||||
const
|
||||
EPS = 1E-3;
|
||||
begin
|
||||
if (AFont1 = nil) and (AFont2 = nil) then
|
||||
Result := true
|
||||
|
@ -356,7 +356,7 @@ end;
|
||||
{ Draw lines in horizontal orienation }
|
||||
procedure TsTextPainter.DrawHor(AOverrideTextColor: TColor);
|
||||
var
|
||||
xpos, ypos, dx, j: Integer;
|
||||
xpos, ypos, j: Integer;
|
||||
lineinfo: TsLineInfo;
|
||||
pEnd: PChar;
|
||||
begin
|
||||
@ -447,7 +447,7 @@ var
|
||||
xpos, ypos, dx: Integer;
|
||||
j: Integer;
|
||||
lineinfo: TsLineInfo;
|
||||
pEnd, p: PChar;
|
||||
pEnd: PChar;
|
||||
begin
|
||||
// (1) Get starting point of line
|
||||
lineinfo := TsLineInfo(FLines[0]);
|
||||
|
@ -331,7 +331,7 @@ begin
|
||||
for j := 0 to lLineSplitter.Tokens.Count-1 do
|
||||
begin
|
||||
lCurToken := lLineSplitter.Tokens[j];
|
||||
FWorksheet.WriteUTF8Text(i, j, lCurToken.Value);
|
||||
FWorksheet.WriteText(i, j, lCurToken.Value);
|
||||
if lCurToken.Bold then
|
||||
FWorksheet.WriteFontStyle(i, j, [fssBold]);
|
||||
if lCurToken.UseBackgroundColor then
|
||||
@ -463,7 +463,7 @@ begin
|
||||
for j := 0 to FWorksheet.GetLastColIndex do
|
||||
begin
|
||||
lCell := FWorksheet.FindCell(i, j);
|
||||
lCurStr := FWorksheet.ReadAsUTF8Text(lCell, fs);
|
||||
lCurStr := FWorksheet.ReadAsText(lCell, fs);
|
||||
// if lCurStr = '' then lCurStr := ' ';
|
||||
|
||||
// Check for invalid characters
|
||||
|
@ -499,7 +499,7 @@ var
|
||||
rtParams: TsRichTextParams;
|
||||
begin
|
||||
if FCommentPending then begin
|
||||
commentStr := ReadWideString(AStream, FCommentLen, rtParams);
|
||||
commentStr := Utf8Encode(ReadWideString(AStream, FCommentLen, rtParams));
|
||||
if commentStr <> '' then
|
||||
begin
|
||||
comment := TBIFF8Comment.Create;
|
||||
@ -2761,7 +2761,7 @@ begin
|
||||
if (cell = nil) or (AHyperlink^.Target='') then
|
||||
exit;
|
||||
|
||||
descr := AWorksheet.ReadAsUTF8Text(cell); // Hyperlink description
|
||||
descr := AWorksheet.ReadAsText(cell); // Hyperlink description
|
||||
SplitHyperlink(AHyperlink^.Target, target, bookmark);
|
||||
u := ParseURI(AHyperlink^.Target);
|
||||
isInternal := (target = '') and (bookmark <> '');
|
||||
|
@ -273,7 +273,7 @@ const
|
||||
{%H-}MIME_XML = 'application/xml';
|
||||
MIME_RELS = 'application/vnd.openxmlformats-package.relationships+xml';
|
||||
MIME_OFFICEDOCUMENT = 'application/vnd.openxmlformats-officedocument';
|
||||
MIME_CORE = 'application/vnd.openxmlformats-package.core-properties+xml';
|
||||
{%H-}MIME_CORE = 'application/vnd.openxmlformats-package.core-properties+xml';
|
||||
MIME_SPREADML = MIME_OFFICEDOCUMENT + '.spreadsheetml';
|
||||
MIME_SHEET = MIME_SPREADML + '.sheet.main+xml';
|
||||
MIME_WORKSHEET = MIME_SPREADML + '.worksheet+xml';
|
||||
@ -2759,7 +2759,7 @@ begin
|
||||
end;
|
||||
if bookmark <> '' then //target = '' then
|
||||
s := Format('%s location="%s"', [s, bookmark]);
|
||||
txt := UTF8TextToXMLText(AWorksheet.ReadAsUTF8Text(hyperlink^.Row, hyperlink^.Col));
|
||||
txt := UTF8TextToXMLText(AWorksheet.ReadAsText(hyperlink^.Row, hyperlink^.Col));
|
||||
if (txt <> '') and (txt <> hyperlink^.Target) then
|
||||
s := Format('%s display="%s"', [s, txt]);
|
||||
if hyperlink^.ToolTip <> '' then begin
|
||||
|
Reference in New Issue
Block a user