You've already forked lazarus-ccr
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:
@ -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.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user