fpspreadsheet: Excel 2003/XML reader supports rich-text formatting.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7044 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2019-07-17 17:22:43 +00:00
parent 347c7328d1
commit 4b1c9b09d1
2 changed files with 50 additions and 10 deletions

View File

@ -41,7 +41,7 @@ type
procedure HTMLToRichText(AWorkbook: TsBasicWorkbook; AFont: TsFont; procedure HTMLToRichText(AWorkbook: TsBasicWorkbook; AFont: TsFont;
const AHTMLText: String; out APlainText: String; const AHTMLText: String; out APlainText: String;
out ARichTextParams: TsRichTextParams); out ARichTextParams: TsRichTextParams; APrefix: String = '');
procedure RichTextToHTML(AWorkbook: TsBasicWorkbook; AFont: TsFont; procedure RichTextToHTML(AWorkbook: TsBasicWorkbook; AFont: TsFont;
const APlainText: String; const ARichTextParams: TsRichTextParams; const APlainText: String; const ARichTextParams: TsRichTextParams;
@ -623,6 +623,7 @@ type
FCurrFont: TsFont; FCurrFont: TsFont;
FPointSeparatorSettings: TFormatSettings; FPointSeparatorSettings: TFormatSettings;
FPreserveSpaces: Boolean; FPreserveSpaces: Boolean;
FPrefix: String;
function AddFont(AFont: TsFont): Integer; function AddFont(AFont: TsFont): Integer;
procedure AddRichTextParam(AFont: TsFont; AHyperlinkIndex: Integer = -1); procedure AddRichTextParam(AFont: TsFont; AHyperlinkIndex: Integer = -1);
procedure ProcessFontRestore; procedure ProcessFontRestore;
@ -633,6 +634,7 @@ type
constructor Create(AWorkbook: TsWorkbook; AFont: TsFont; AText: String); constructor Create(AWorkbook: TsWorkbook; AFont: TsFont; AText: String);
destructor Destroy; override; destructor Destroy; override;
property PlainText: String read FPlainText; property PlainText: String read FPlainText;
property Prefix: String read FPrefix write FPrefix;
property RichTextParams: TsRichTextParams read FRichTextParams; property RichTextParams: TsRichTextParams read FRichTextParams;
property PreserveSpaces: Boolean read FPreserveSpaces write FPreserveSpaces; property PreserveSpaces: Boolean read FPreserveSpaces write FPreserveSpaces;
end; end;
@ -738,9 +740,9 @@ var
f: Double; f: Double;
defFntSize: Single; defFntSize: Single;
begin begin
idx := FAttrList.IndexOfName('font-family'); // style tag idx := FAttrList.IndexOfName(FPrefix + 'font-family'); // style tag
if idx = -1 then if idx = -1 then
idx := FAttrList.IndexOfName('face'); // html tag idx := FAttrList.IndexOfName(FPrefix + 'face'); // html tag
if idx > -1 then begin if idx > -1 then begin
L := TStringList.Create; L := TStringList.Create;
try try
@ -752,9 +754,9 @@ begin
end; end;
end; end;
idx := FAttrList.IndexOfName('font-size'); idx := FAttrList.IndexOfName(FPrefix + 'font-size');
if idx = -1 then if idx = -1 then
idx := FAttrList.IndexOfName('size'); idx := FAttrList.IndexOfName(FPrefix + 'size');
if idx > -1 then begin if idx > -1 then begin
defFntSize := FWorkbook.GetDefaultFont.Size; defFntSize := FWorkbook.GetDefaultFont.Size;
s := FAttrList[idx].Value; s := FAttrList[idx].Value;
@ -799,7 +801,7 @@ begin
end; end;
end; end;
idx := FAttrList.IndexOfName('font-style'); idx := FAttrList.IndexOfName(FPrefix + 'font-style');
if idx > -1 then if idx > -1 then
case FAttrList[idx].Value of case FAttrList[idx].Value of
'normal' : Exclude(AFont.Style, fssItalic); 'normal' : Exclude(AFont.Style, fssItalic);
@ -807,14 +809,14 @@ begin
'oblique' : Include(AFont.Style, fssItalic); 'oblique' : Include(AFont.Style, fssItalic);
end; end;
idx := FAttrList.IndexOfName('font-weight'); idx := FAttrList.IndexOfName(FPrefix + 'font-weight');
if idx > -1 then if idx > -1 then
begin begin
s := FAttrList[idx].Value; s := FAttrList[idx].Value;
if TryStrToInt(s, i) and (i >= 700) then Include(AFont.Style, fssBold); if TryStrToInt(s, i) and (i >= 700) then Include(AFont.Style, fssBold);
end; end;
idx := FAttrList.IndexOfName('text-decoration'); idx := FAttrList.IndexOfName(FPrefix + 'text-decoration');
if idx > -1 then if idx > -1 then
begin begin
s := FAttrList[idx].Value; s := FAttrList[idx].Value;
@ -822,7 +824,7 @@ begin
if pos('line-through', s) <> 0 then Include(AFont.Style, fssStrikeout); if pos('line-through', s) <> 0 then Include(AFont.Style, fssStrikeout);
end; end;
idx := FAttrList.IndexOfName('color'); idx := FAttrList.IndexOfName(FPrefix + 'color');
if idx > -1 then if idx > -1 then
AFont.Color := HTMLColorStrToColor(FAttrList[idx].Value); AFont.Color := HTMLColorStrToColor(FAttrList[idx].Value);
end; end;
@ -942,7 +944,7 @@ end;
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
procedure HTMLToRichText(AWorkbook: TsBasicWorkbook; AFont: TsFont; procedure HTMLToRichText(AWorkbook: TsBasicWorkbook; AFont: TsFont;
const AHTMLText: String; out APlainText: String; const AHTMLText: String; out APlainText: String;
out ARichTextParams: TsRichTextParams); out ARichTextParams: TsRichTextParams; APrefix: String = '');
var var
analyzer: TsHTMLAnalyzer; analyzer: TsHTMLAnalyzer;
j: Integer; j: Integer;
@ -952,6 +954,7 @@ begin
analyzer := TsHTMLAnalyzer.Create(AWorkbook as TsWorkbook, AFont, AHTMLText + '<end>'); analyzer := TsHTMLAnalyzer.Create(AWorkbook as TsWorkbook, AFont, AHTMLText + '<end>');
try try
analyzer.PreserveSpaces := true; analyzer.PreserveSpaces := true;
analyzer.Prefix := APrefix;
analyzer.Exec; analyzer.Exec;
APlainText := analyzer.PlainText; APlainText := analyzer.PlainText;
nrtp := Length(analyzer.RichTextParams); nrtp := Length(analyzer.RichTextParams);

View File

@ -195,6 +195,33 @@ begin
end; end;
end; end;
{ Helper routine to rebuild the html content of the "ss:Data" nodes }
procedure RebuildChildNodes(ANode: TDOMNode; var AText: String);
var
nodeName: String;
s: String;
i: Integer;
begin
if ANode = nil then
exit;
while ANode <> nil do begin
nodeName := ANode.NodeName;
if nodeName = '#text' then
AText := AText + ANode.NodeValue
else begin
s := '';
for i := 0 to ANode.Attributes.Length-1 do
s := Format('%s %s="%s"', [s, ANode.Attributes.Item[i].NodeName, ANode.Attributes.Item[i].NodeValue]);
AText := Format('%s<%s%s>', [AText, nodeName, s]);
s := '';
RebuildChildNodes(ANode.FirstChild, s);
if s <> '' then
AText := Format('%s%s</%s>', [AText, s, nodeName]);
end;
ANode := ANode.NextSibling;
end;
end;
{=============================================================================== {===============================================================================
TsSpreadExcelXMLReader TsSpreadExcelXMLReader
@ -414,12 +441,15 @@ var
sheet: TsWorksheet absolute AWorksheet; sheet: TsWorksheet absolute AWorksheet;
nodeName: string; nodeName: string;
s, st, sv: String; s, st, sv: String;
txt: String;
node: TDOMNode; node: TDOMNode;
err: TsErrorValue; err: TsErrorValue;
cell: PCell; cell: PCell;
fmt: TsCellFormat; fmt: TsCellFormat;
idx: Integer; idx: Integer;
mergedCols, mergedRows: Integer; mergedCols, mergedRows: Integer;
font: TsFont;
rtp: TsRichTextParams;
begin begin
if ANode = nil then if ANode = nil then
exit; exit;
@ -429,6 +459,7 @@ begin
cell := sheet.GetCell(ARow, ACol); cell := sheet.GetCell(ARow, ACol);
book := TsWorkbook(FWorkbook); book := TsWorkbook(FWorkbook);
font := book.GetDefaultFont;
s := GetAttrValue(ANode, 'ss:StyleID'); s := GetAttrValue(ANode, 'ss:StyleID');
if s <> '' then begin if s <> '' then begin
@ -436,6 +467,7 @@ begin
if idx <> -1 then begin if idx <> -1 then begin
fmt := FCellFormatList.Items[idx]^; fmt := FCellFormatList.Items[idx]^;
cell^.FormatIndex := book.AddCellFormat(fmt); cell^.FormatIndex := book.AddCellFormat(fmt);
font := book.GetFont(fmt.FontIndex);;
end; end;
end; end;
@ -499,6 +531,11 @@ begin
if TryStrToErrorValue(sv, err) then if TryStrToErrorValue(sv, err) then
sheet.WriteErrorValue(cell, err); sheet.WriteErrorValue(cell, err);
end; end;
if nodeName = 'ss:Data' then begin
txt := '';
RebuildChildNodes(node, txt);
HTMLToRichText(FWorkbook, font, txt, s, cell^.RichTextParams, 'html:');
end;
end end
else else
if (nodeName = 'Comment') then if (nodeName = 'Comment') then