fpspreadsheet: Reading of xlsx theme colors working (writing is not planned). xlsx reader now creates a default color palette because some xlsx files refer to colors by index although they don't contain a palette.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3442 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-08-06 21:52:20 +00:00
parent c5d2cdde62
commit 2fd7d0caa1

View File

@ -159,7 +159,7 @@ type
implementation implementation
uses uses
variants, fileutil, StrUtils, fpsStreams, fpsNumFormatParser; variants, fileutil, StrUtils, math, fpsStreams, fpsNumFormatParser;
const const
{ OOXML general XML constants } { OOXML general XML constants }
@ -201,6 +201,82 @@ const
MIME_STYLES = MIME_SPREADML + '.styles+xml'; MIME_STYLES = MIME_SPREADML + '.styles+xml';
MIME_STRINGS = MIME_SPREADML + '.sharedStrings+xml'; MIME_STRINGS = MIME_SPREADML + '.sharedStrings+xml';
LAST_PALETTE_COLOR = $3F; // 63
var
// the palette of the 64 default colors as "big-endian color" values
// (identical to BIFF8)
PALETTE_OOXML: array[$00..LAST_PALETTE_COLOR] of TsColorValue = (
$000000, // $00: black // 8 built-in default colors
$FFFFFF, // $01: white
$FF0000, // $02: red
$00FF00, // $03: green
$0000FF, // $04: blue
$FFFF00, // $05: yellow
$FF00FF, // $06: magenta
$00FFFF, // $07: cyan
$000000, // $08: EGA black
$FFFFFF, // $09: EGA white
$FF0000, // $0A: EGA red
$00FF00, // $0B: EGA green
$0000FF, // $0C: EGA blue
$FFFF00, // $0D: EGA yellow
$FF00FF, // $0E: EGA magenta
$00FFFF, // $0F: EGA cyan
$800000, // $10: EGA dark red
$008000, // $11: EGA dark green
$000080, // $12: EGA dark blue
$808000, // $13: EGA olive
$800080, // $14: EGA purple
$008080, // $15: EGA teal
$C0C0C0, // $16: EGA silver
$808080, // $17: EGA gray
$9999FF, // $18:
$993366, // $19:
$FFFFCC, // $1A:
$CCFFFF, // $1B:
$660066, // $1C:
$FF8080, // $1D:
$0066CC, // $1E:
$CCCCFF, // $1F:
$000080, // $20:
$FF00FF, // $21:
$FFFF00, // $22:
$00FFFF, // $23:
$800080, // $24:
$800000, // $25:
$008080, // $26:
$0000FF, // $27:
$00CCFF, // $28:
$CCFFFF, // $29:
$CCFFCC, // $2A:
$FFFF99, // $2B:
$99CCFF, // $2C:
$FF99CC, // $2D:
$CC99FF, // $2E:
$FFCC99, // $2F:
$3366FF, // $30:
$33CCCC, // $31:
$99CC00, // $32:
$FFCC00, // $33:
$FF9900, // $34:
$FF6600, // $35:
$666699, // $36:
$969696, // $37:
$003366, // $38:
$339966, // $39:
$003300, // $3A:
$333300, // $3B:
$993300, // $3C:
$993366, // $3D:
$333399, // $3E:
$333333 // $3F:
);
type type
TFillListData = class TFillListData = class
PatternType: String; PatternType: String;
@ -714,6 +790,7 @@ var
rgba: TRGBA absolute(rgb); // just for debugging rgba: TRGBA absolute(rgb); // just for debugging
idx: Integer; idx: Integer;
tint: Double; tint: Double;
n: Integer;
begin begin
Assert(ANode <> nil); Assert(ANode <> nil);
@ -726,8 +803,23 @@ begin
s := GetAttrValue(ANode, 'indexed'); s := GetAttrValue(ANode, 'indexed');
if s <> '' then begin if s <> '' then begin
Result := StrToInt(s); Result := StrToInt(s);
if (Result >= FWorkbook.GetPaletteSize) then n := FWorkbook.GetPaletteSize;
Result := scBlack; if (Result <= LAST_PALETTE_COLOR) and (Result < FWorkbook.GetPaletteSize) then
exit;
// System colors
// taken from OpenOffice docs
case Result of
$0040: Result := scBlack; // Default border color
$0041: Result := scWhite; // Default background color
$0043: Result := scGray; // Dialog background color
$004D: Result := scBlack; // Text color, chart border lines
$004E: Result := scGray; // Background color for chart areas
$004F: Result := scBlack; // Automatic color for chart border lines
$0050: Result := scBlack; // ???
$0051: Result := scBlack; // ??
$7FFF: Result := scBlack; // ??
else Result := scBlack;
end;
exit; exit;
end; end;
@ -735,7 +827,14 @@ begin
if s <> '' then begin if s <> '' then begin
idx := StrToInt(s); idx := StrToInt(s);
if idx < Length(FThemeColors) then begin if idx < Length(FThemeColors) then begin
rgb := FThemeColors[StrToInt(s)]; // For some reason the first two pairs of colors are interchanged in Excel!
case idx of
0: idx := 1;
1: idx := 0;
2: idx := 3;
3: idx := 2;
end;
rgb := FThemeColors[idx];
s := GetAttrValue(ANode, 'tint'); s := GetAttrValue(ANode, 'tint');
if s <> '' then begin if s <> '' then begin
tint := StrToFloat(s, FPointSeparatorSettings); tint := StrToFloat(s, FPointSeparatorSettings);
@ -977,15 +1076,20 @@ procedure TsSpreadOOXMLReader.ReadPalette(ANode: TDOMNode);
var var
node, colornode: TDOMNode; node, colornode: TDOMNode;
nodename: String; nodename: String;
rgb: string; s: string;
clr: TsColor;
rgb: TsColorValue;
n: Integer; n: Integer;
color: TsColorValue;
pal: array of TsColorValue;
begin begin
// OOXML sometimes specifies color by index even if a palette ("indexedColors")
// is not loaeded. Therefore, we use the BIFF8 palette as default because
// the default indexedColors are identical to it.
n := Length(PALETTE_OOXML);
FWorkbook.UsePalette(@PALETTE_OOXML, n);
if ANode = nil then if ANode = nil then
exit; exit;
SetLength(pal, 1000);
n := 0; clr := 0;
node := ANode.FirstChild; node := ANode.FirstChild;
while Assigned(node) do begin while Assigned(node) do begin
nodename := node.NodeName; nodename := node.NodeName;
@ -994,13 +1098,15 @@ begin
while Assigned(colornode) do begin while Assigned(colornode) do begin
nodename := colornode.NodeName; nodename := colornode.NodeName;
if nodename = 'rgbColor' then begin if nodename = 'rgbColor' then begin
rgb := GetAttrValue(colornode, 'rgb'); s := GetAttrValue(colornode, 'rgb');
if rgb <> '' then begin if s <> '' then begin
color := HTMLColorStrToColor('#' + rgb); rgb := HTMLColorStrToColor('#' + s);
if n = Length(pal) then if clr < n then begin
SetLength(pal, Length(pal) + 1000); FWorkbook.SetPaletteColor(clr, rgb);
pal[n] := color; inc(clr);
inc(n); end
else
FWorkbook.AddColorToPalette(rgb);
end; end;
end; end;
colornode := colorNode.NextSibling; colornode := colorNode.NextSibling;
@ -1008,7 +1114,6 @@ begin
end; end;
node := node.NextSibling; node := node.NextSibling;
end; end;
FWorkbook.UsePalette(@pal[0], n);
end; end;
procedure TsSpreadOOXMLReader.ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet); procedure TsSpreadOOXMLReader.ReadRowHeight(ANode: TDOMNode; AWorksheet: TsWorksheet);
@ -1721,7 +1826,9 @@ begin
'<colors>' + '<colors>' +
'<indexedColors>'); '<indexedColors>');
for i:=0 to Workbook.GetPaletteSize-1 do begin // There must not be more than 64 palette entries because the next colors
// are system colors.
for i:=0 to Min(LAST_PALETTE_COLOR, Workbook.GetPaletteSize-1) do begin
rgb := Workbook.GetPaletteColor(i); rgb := Workbook.GetPaletteColor(i);
AppendToStream(AStream, AppendToStream(AStream,
'<rgbColor rgb="'+ColorToHTMLColorStr(rgb, true) + '" />'); '<rgbColor rgb="'+ColorToHTMLColorStr(rgb, true) + '" />');
@ -2463,6 +2570,7 @@ end;
initialization initialization
RegisterSpreadFormat(TsSpreadOOXMLReader, TsSpreadOOXMLWriter, sfOOXML); RegisterSpreadFormat(TsSpreadOOXMLReader, TsSpreadOOXMLWriter, sfOOXML);
MakeLEPalette(@PALETTE_OOXML, Length(PALETTE_OOXML));
end. end.