You've already forked lazarus-ccr
fpspreadsheet: Add ods reading support for cell borders, border line styles and border colors. Borders of ods files are displayed in fpsgrid correctly.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3106 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -74,6 +74,7 @@ type
|
|||||||
procedure ReadNumFormats(AStylesNode: TDOMNode);
|
procedure ReadNumFormats(AStylesNode: TDOMNode);
|
||||||
procedure ReadStyles(AStylesNode: TDOMNode);
|
procedure ReadStyles(AStylesNode: TDOMNode);
|
||||||
{ Record writing methods }
|
{ Record writing methods }
|
||||||
|
procedure ReadBlank(ARow, ACol: Word; ACellNode: TDOMNode);
|
||||||
procedure ReadFormula(ARow : Word; ACol : Word; ACellNode: TDOMNode);
|
procedure ReadFormula(ARow : Word; ACol : Word; ACellNode: TDOMNode);
|
||||||
procedure ReadLabel(ARow : Word; ACol : Word; ACellNode: TDOMNode);
|
procedure ReadLabel(ARow : Word; ACol : Word; ACellNode: TDOMNode);
|
||||||
procedure ReadNumber(ARow : Word; ACol : Word; ACellNode: TDOMNode);
|
procedure ReadNumber(ARow : Word; ACol : Word; ACellNode: TDOMNode);
|
||||||
@ -332,6 +333,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TsSpreadOpenDocReader.ReadBlank(ARow, ACol: Word; ACellNode: TDOMNode);
|
||||||
|
var
|
||||||
|
styleName: String;
|
||||||
|
begin
|
||||||
|
FWorkSheet.WriteBlank(ARow, ACol);
|
||||||
|
|
||||||
|
styleName := GetAttrValue(ACellNode, 'table:style-name');
|
||||||
|
ApplyStyleToCell(ARow, ACol, stylename);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadDateMode(SpreadSheetNode: TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadDateMode(SpreadSheetNode: TDOMNode);
|
||||||
var
|
var
|
||||||
CalcSettingsNode, NullDateNode: TDOMNode;
|
CalcSettingsNode, NullDateNode: TDOMNode;
|
||||||
@ -433,6 +444,8 @@ begin
|
|||||||
ReadNumber(Row, Col, CellNode)
|
ReadNumber(Row, Col, CellNode)
|
||||||
else if (ParamValueType = 'date') or (ParamValueType = 'time') then
|
else if (ParamValueType = 'date') or (ParamValueType = 'time') then
|
||||||
ReadDate(Row, Col, CellNode)
|
ReadDate(Row, Col, CellNode)
|
||||||
|
else if (ParamValueType = '') then
|
||||||
|
ReadBlank(Row, Col, CellNode)
|
||||||
else if ParamFormula <> '' then
|
else if ParamFormula <> '' then
|
||||||
ReadLabel(Row, Col, CellNode);
|
ReadLabel(Row, Col, CellNode);
|
||||||
|
|
||||||
@ -464,9 +477,14 @@ begin
|
|||||||
ReadNumber(ARow, ACol, ACellNode);
|
ReadNumber(ARow, ACol, ACellNode);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadLabel(ARow: Word; ACol : Word; ACellNode : TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadLabel(ARow: Word; ACol: Word; ACellNode: TDOMNode);
|
||||||
|
var
|
||||||
|
styleName: String;
|
||||||
begin
|
begin
|
||||||
FWorkSheet.WriteUTF8Text(ARow,ACol,UTF8Encode(ACellNode.TextContent));
|
FWorkSheet.WriteUTF8Text(ARow, ACol, UTF8Encode(ACellNode.TextContent));
|
||||||
|
|
||||||
|
styleName := GetAttrValue(ACellNode, 'table:style-name');
|
||||||
|
ApplyStyleToCell(ARow, ACol, stylename);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadNumber(ARow: Word; ACol : Word; ACellNode : TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadNumber(ARow: Word; ACol : Word; ACellNode : TDOMNode);
|
||||||
@ -728,6 +746,7 @@ end;
|
|||||||
|
|
||||||
procedure TsSpreadOpenDocReader.ReadStyles(AStylesNode: TDOMNode);
|
procedure TsSpreadOpenDocReader.ReadStyles(AStylesNode: TDOMNode);
|
||||||
var
|
var
|
||||||
|
fs: TFormatSettings;
|
||||||
style: TStyleData;
|
style: TStyleData;
|
||||||
styleNode: TDOMNode;
|
styleNode: TDOMNode;
|
||||||
styleChildNode: TDOMNode;
|
styleChildNode: TDOMNode;
|
||||||
@ -739,11 +758,78 @@ var
|
|||||||
numFmtIndexDefault: Integer;
|
numFmtIndexDefault: Integer;
|
||||||
wrap: Boolean;
|
wrap: Boolean;
|
||||||
borders: TsCellBorders;
|
borders: TsCellBorders;
|
||||||
|
borderStyles: TsCellBorderStyles;
|
||||||
s: String;
|
s: String;
|
||||||
|
|
||||||
|
procedure SetBorderStyle(ABorder: TsCellBorder; AStyleValue: String);
|
||||||
|
var
|
||||||
|
L: TStringList;
|
||||||
|
i: Integer;
|
||||||
|
isSolid: boolean;
|
||||||
|
s: String;
|
||||||
|
wid: Double;
|
||||||
|
linestyle: String;
|
||||||
|
rgb: DWord;
|
||||||
|
p: Integer;
|
||||||
|
begin
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
L.Delimiter := ' ';
|
||||||
|
L.StrictDelimiter := true;
|
||||||
|
L.DelimitedText := AStyleValue;
|
||||||
|
wid := 0;
|
||||||
|
rgb := 0;
|
||||||
|
linestyle := '';
|
||||||
|
for i:=0 to L.Count-1 do begin
|
||||||
|
s := L[i];
|
||||||
|
if (s = 'solid') or (s = 'dashed') or (s = 'fine-dashed') or (s = 'dotted')
|
||||||
|
then linestyle := s;
|
||||||
|
if s[1] = '#' then begin
|
||||||
|
s[1] := '$';
|
||||||
|
rgb := StrToInt(s);
|
||||||
|
end;
|
||||||
|
p := pos('pt', s);
|
||||||
|
if p = Length(s)-1 then begin
|
||||||
|
wid := StrToFloat(copy(s, 1, p-1), fs);
|
||||||
|
continue;
|
||||||
|
end;
|
||||||
|
p := pos('mm', s);
|
||||||
|
if p = Length(s)-1 then begin
|
||||||
|
wid := mmToPts(StrToFloat(copy(s, 1, p-1), fs));
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
p := pos('cm', s);
|
||||||
|
if p = Length(s)-1 then begin
|
||||||
|
wid := cmToPts(StrToFloat(copy(s, 1, p-1), fs));
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
borderStyles[ABorder].LineStyle := lsThin;
|
||||||
|
if (linestyle = 'solid') then begin
|
||||||
|
if (wid >= 2) then borderStyles[ABorder].LineStyle := lsThick
|
||||||
|
else if (wid >= 1) then borderStyles[ABorder].LineStyle := lsMedium
|
||||||
|
end else
|
||||||
|
if (linestyle = 'dotted') then
|
||||||
|
borderStyles[ABorder].LineStyle := lsHair
|
||||||
|
else
|
||||||
|
if (linestyle = 'dashed') then
|
||||||
|
borderStyles[ABorder].LineStyle := lsDashed
|
||||||
|
else
|
||||||
|
if (linestyle = 'fine-dashed') then
|
||||||
|
borderStyles[ABorder].LineStyle := lsDotted;
|
||||||
|
borderStyles[ABorder].Color := Workbook.AddColorToPalette(LongRGBToExcelPhysical(rgb));
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if not Assigned(AStylesNode) then
|
if not Assigned(AStylesNode) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
fs := DefaultFormatSettings;
|
||||||
|
fs.DecimalSeparator := '.';
|
||||||
|
|
||||||
numFmtIndexDefault := NumFormatList.FindByName('N0');
|
numFmtIndexDefault := NumFormatList.FindByName('N0');
|
||||||
|
|
||||||
styleNode := AStylesNode.FirstChild;
|
styleNode := AStylesNode.FirstChild;
|
||||||
@ -764,14 +850,34 @@ begin
|
|||||||
while Assigned(styleChildNode) do begin
|
while Assigned(styleChildNode) do begin
|
||||||
if styleChildNode.NodeName = 'style:table-cell-properties' then begin
|
if styleChildNode.NodeName = 'style:table-cell-properties' then begin
|
||||||
// Borders
|
// Borders
|
||||||
|
s := GetAttrValue(styleChildNode, 'fo:border');
|
||||||
|
if (s <>'') then begin
|
||||||
|
borders := borders + [cbNorth, cbSouth, cbEast, cbWest];
|
||||||
|
SetBorderStyle(cbNorth, s);
|
||||||
|
SetBorderStyle(cbSouth, s);
|
||||||
|
SetBorderStyle(cbEast, s);
|
||||||
|
SetBorderStyle(cbWest, s);
|
||||||
|
end;
|
||||||
s := GetAttrValue(styleChildNode, 'fo:border-top');
|
s := GetAttrValue(styleChildNode, 'fo:border-top');
|
||||||
if (s <> '') and (s <> 'none') then Include(borders, cbNorth);
|
if (s <> '') and (s <> 'none') then begin
|
||||||
|
Include(borders, cbNorth);
|
||||||
|
SetBorderStyle(cbNorth, s);
|
||||||
|
end;
|
||||||
s := GetAttrValue(styleChildNode, 'fo:border-right');
|
s := GetAttrValue(styleChildNode, 'fo:border-right');
|
||||||
if (s <> '') and (s <> 'none') then Include(borders, cbEast);
|
if (s <> '') and (s <> 'none') then begin
|
||||||
|
Include(borders, cbEast);
|
||||||
|
SetBorderStyle(cbEast, s);
|
||||||
|
end;
|
||||||
s := GetAttrValue(styleChildNode, 'fo:border-bottom');
|
s := GetAttrValue(styleChildNode, 'fo:border-bottom');
|
||||||
if (s <> '') and (s <> 'none') then Include(borders, cbSouth);
|
if (s <> '') and (s <> 'none') then begin
|
||||||
|
Include(borders, cbSouth);
|
||||||
|
SetBorderStyle(cbSouth, s);
|
||||||
|
end;
|
||||||
s := GetAttrValue(styleChildNode, 'fo:border-left');
|
s := GetAttrValue(styleChildNode, 'fo:border-left');
|
||||||
if (s <> '') and (s <> 'none') then Include(borders, cbWest);
|
if (s <> '') and (s <> 'none') then begin
|
||||||
|
Include(borders, cbWest);
|
||||||
|
SetBorderStyle(cbWest, s);
|
||||||
|
end;
|
||||||
|
|
||||||
// Text wrap
|
// Text wrap
|
||||||
s := GetAttrValue(styleChildNode, 'fo:wrap-option');
|
s := GetAttrValue(styleChildNode, 'fo:wrap-option');
|
||||||
@ -792,7 +898,7 @@ begin
|
|||||||
style.WordWrap := wrap;
|
style.WordWrap := wrap;
|
||||||
style.TextRotation := trHorizontal;
|
style.TextRotation := trHorizontal;
|
||||||
style.Borders := borders;
|
style.Borders := borders;
|
||||||
style.BorderStyles := DEFAULT_BORDERSTYLES;
|
style.BorderStyles := borderStyles;
|
||||||
style.BackgroundColor := scNotDefined;
|
style.BackgroundColor := scNotDefined;
|
||||||
|
|
||||||
styleIndex := FStyleList.Add(style);
|
styleIndex := FStyleList.Add(style);
|
||||||
|
@ -550,6 +550,7 @@ type
|
|||||||
procedure RemoveAllFonts;
|
procedure RemoveAllFonts;
|
||||||
procedure SetDefaultFont(const AFontName: String; ASize: Single);
|
procedure SetDefaultFont(const AFontName: String; ASize: Single);
|
||||||
{ Color handling }
|
{ Color handling }
|
||||||
|
function AddColorToPalette(AColorValue: TsColorValue): TsColor;
|
||||||
function FPSColorToHexString(AColor: TsColor; ARGBColor: TFPColor): String;
|
function FPSColorToHexString(AColor: TsColor; ARGBColor: TFPColor): String;
|
||||||
function GetColorName(AColorIndex: TsColor): string;
|
function GetColorName(AColorIndex: TsColor): string;
|
||||||
function GetPaletteColor(AColorIndex: TsColor): TsColorValue;
|
function GetPaletteColor(AColorIndex: TsColor): TsColorValue;
|
||||||
@ -2831,6 +2832,33 @@ begin
|
|||||||
Result := FFontList.Count;
|
Result := FFontList.Count;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{@@
|
||||||
|
Adds a color to the palette and returns its palette index, but only if the
|
||||||
|
color does not already exist - in this case, it returns the index of the
|
||||||
|
existing color entry. }
|
||||||
|
function TsWorkbook.AddColorToPalette(AColorValue: TsColorValue): TsColor;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
// No palette yet? Add the 16 first entries of the default_palette. They are
|
||||||
|
// common to all palettes
|
||||||
|
if Length(FPalette) = 0 then begin
|
||||||
|
SetLength(FPalette, 16);
|
||||||
|
for i := 0 to 15 do
|
||||||
|
FPalette[i] := DEFAULT_PALETTE[i];
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Now look for the color. Is already in the existing palette?
|
||||||
|
for Result := 0 to Length(FPalette)-1 do
|
||||||
|
if FPalette[Result] = AColorValue then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
// No. Add it to the palette.
|
||||||
|
Result := Length(FPalette);
|
||||||
|
SetLength(FPalette, Result+1);
|
||||||
|
FPalette[Result] := AColorValue;
|
||||||
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Converts a fpspreadsheet color into into a string RRGGBB.
|
Converts a fpspreadsheet color into into a string RRGGBB.
|
||||||
Note that colors are written to xls files as ABGR (where A is 0).
|
Note that colors are written to xls files as ABGR (where A is 0).
|
||||||
|
@ -102,6 +102,9 @@ function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
|||||||
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
|
||||||
const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string;
|
const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string;
|
||||||
|
|
||||||
|
function cmToPts(AValue: Double): Double;
|
||||||
|
function mmToPts(AValue: Double): Double;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -1290,5 +1293,17 @@ begin
|
|||||||
DateTimeToString(Result, FormatStr, DateTime, FormatSettings,Options);
|
DateTimeToString(Result, FormatStr, DateTime, FormatSettings,Options);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Converts centimeters to points (72 pts = 1 inch) }
|
||||||
|
function cmToPts(AValue: Double): Double;
|
||||||
|
begin
|
||||||
|
Result := AValue/(2.54*72);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Converts millimeters to points (72 pts = 1 inch) }
|
||||||
|
function mmToPts(AValue: Double): Double;
|
||||||
|
begin
|
||||||
|
Result := AValue/(25.4*72);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user