fpspreadsheet: Read/write worksheet hidden state for biff8 and biff5.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5775 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2017-03-01 20:01:14 +00:00
parent 59c6c664f9
commit 4ce25109a8
3 changed files with 116 additions and 89 deletions

View File

@ -100,7 +100,7 @@ type
procedure InternalWriteToStream(AStream: TStream);
{ Record writing methods }
procedure WriteBOF(AStream: TStream; ADataType: Word);
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
function WriteBoundsheet(AStream: TStream; AWorkSheet: TsWorksheet): Int64;
procedure WriteDefinedName(AStream: TStream; AWorksheet: TsWorksheet;
const AName: String; AIndexToREF: Word); override;
procedure WriteDimensions(AStream: TStream; AWorksheet: TsWorksheet);
@ -364,9 +364,10 @@ end;
-------------------------------------------------------------------------------}
procedure TsSpreadBIFF5Reader.ReadBoundsheet(AStream: TStream);
var
Len: Byte;
len: Byte;
s: AnsiString;
sheetName: String;
sheetState: Byte;
sheetData: TsSheetData;
begin
{ Absolute stream position of the BOF record of the sheet represented
by this record }
@ -374,18 +375,21 @@ begin
AStream.ReadDWord();
{ Visibility }
AStream.ReadByte();
sheetState := AStream.ReadByte();
{ Sheet type }
AStream.ReadByte();
{ Sheet name: Byte string, 8-bit length }
Len := AStream.ReadByte();
len := AStream.ReadByte();
SetLength(s, len);
AStream.ReadBuffer(s[1], len*SizeOf(AnsiChar));
SetLength(s, Len);
AStream.ReadBuffer(s[1], Len*SizeOf(AnsiChar));
sheetName := ConvertEncoding(s, FCodePage, EncodingUTF8);
FWorksheetNames.Add(sheetName);
{ Temporarily store parameters for worksheet in FSheetList }
sheetData := TsSheetData.Create;
sheetData.Name := ConvertEncoding(s, FCodePage, EncodingUTF8);
sheetData.Hidden := sheetState <> 0;
FSheetList.Add(sheetData);
end;
{@@ ----------------------------------------------------------------------------
@ -494,8 +498,12 @@ var
SectionEOF: Boolean = False;
RecordType: Word;
CurStreamPos: Int64;
sheetData: TsSheetData;
begin
FWorksheet := FWorkbook.AddWorksheet(FWorksheetNames[FCurSheetIndex], true);
sheetData := TsSheetData(FSheetList[FCurSheetIndex]);
FWorksheet := FWorkbook.AddWorksheet(sheetData.Name, true);
if sheetData.Hidden then
FWorksheet.Options := FWorksheet.Options + [soHidden];
while (not SectionEOF) do
begin
@ -1101,7 +1109,7 @@ end;
procedure TsSpreadBIFF5Writer.InternalWriteToStream(AStream: TStream);
var
CurrentPos: Int64;
Boundsheets: array of Int64;
sheetPos: array of Int64;
i: Integer;
pane: Byte;
begin
@ -1121,9 +1129,9 @@ begin
WriteStyle(AStream);
// A BOUNDSHEET for each worksheet
SetLength(Boundsheets, Workbook.GetWorksheetCount);
SetLength(sheetPos, Workbook.GetWorksheetCount);
for i := 0 to Workbook.GetWorksheetCount - 1 do
Boundsheets[i] := WriteBoundsheet(AStream, Workbook.GetWorksheetByIndex(i).Name);
sheetPos[i] := WriteBoundsheet(AStream, Workbook.GetWorksheetByIndex(i));
WriteEOF(AStream);
@ -1136,7 +1144,7 @@ begin
{ First goes back and writes the position of the BOF of the
sheet on the respective BOUNDSHEET record }
CurrentPos := AStream.Position;
AStream.Position := Boundsheets[i];
AStream.Position := sheetPos[i];
AStream.WriteDWord(CurrentPos);
AStream.Position := CurrentPos;
@ -1179,7 +1187,7 @@ begin
{ Cleanup }
SetLength(Boundsheets, 0);
SetLength(sheetPos, 0);
end;
{@@ ----------------------------------------------------------------------------
@ -1281,13 +1289,15 @@ end;
@return The stream position where the absolute stream position
of the BOF of this sheet should be written (4 bytes size).
-------------------------------------------------------------------------------}
function TsSpreadBIFF5Writer.WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
function TsSpreadBIFF5Writer.WriteBoundsheet(AStream: TStream;
AWorkSheet: TsWorksheet): Int64;
var
Len: Byte;
len: Byte;
xlsSheetName: ansistring;
sheetState: Byte;
begin
xlsSheetName := ConvertEncoding(ASheetName, encodingUTF8, FCodePage);
Len := Length(xlsSheetName);
xlsSheetName := ConvertEncoding(AWorkSheet.Name, encodingUTF8, FCodePage);
len := Length(xlsSheetName);
{
LatinSheetName := UTF8ToISO_8859_1(ASheetName);
Len := Length(LatinSheetName);
@ -1301,15 +1311,16 @@ begin
AStream.WriteDWord(WordToLE(0));
{ Visibility }
AStream.WriteByte(0);
sheetState := IfThen(soHidden in AWorksheet.Options, 1, 0);
AStream.WriteByte(sheetState);
{ Sheet type }
AStream.WriteByte(0);
{ Sheet name: Byte string, 8-bit length }
AStream.WriteByte(Len);
AStream.WriteByte(len);
// AStream.WriteBuffer(LatinSheetName[1], Len);
AStream.WriteBuffer(xlsSheetName[1], Len);
AStream.WriteBuffer(xlsSheetName[1], len);
end;
{@@ ----------------------------------------------------------------------------

View File

@ -65,7 +65,6 @@ uses
fpsutils;
type
TBIFF8ExternSheet = packed record
ExternBookIndex: Word;
FirstSheetIndex: Word;
@ -139,7 +138,7 @@ type
{ Record writing methods }
procedure WriteBOF(AStream: TStream; ADataType: Word);
function WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
function WriteBoundsheet(AStream: TStream; AWorksheet: TsWorksheet): Int64;
procedure WriteComment(AStream: TStream; ACell: PCell); override;
procedure WriteComments(AStream: TStream; AWorksheet: TsWorksheet);
procedure WriteDefinedName(AStream: TStream; AWorksheet: TsWorksheet;
@ -454,6 +453,7 @@ type
Text: String;
end;
{ TsSpreadBIFF8Reader }
destructor TsSpreadBIFF8Reader.Destroy;
@ -830,8 +830,12 @@ var
SectionEOF: Boolean = False;
RecordType: Word;
CurStreamPos: Int64;
sheetData: TsSheetData;
begin
FWorksheet := FWorkbook.AddWorksheet(FWorksheetNames[FCurSheetIndex], true);
sheetData := TsSheetData(FSheetList[FCurSheetIndex]);
FWorksheet := FWorkbook.AddWorksheet(sheetData.Name, true);
if sheetData.Hidden then
FWorksheet.Options := FWorksheet.Options + [soHidden];
while (not SectionEOF) do
begin
@ -912,9 +916,11 @@ end;
procedure TsSpreadBIFF8Reader.ReadBoundsheet(AStream: TStream);
var
Len: Byte;
WideName: WideString;
len: Byte;
wideName: WideString;
rtParams: TsRichTextParams;
sheetstate: Byte;
sheetdata: TsSheetData;
begin
{ Absolute stream position of the BOF record of the sheet represented
by this record }
@ -922,18 +928,21 @@ begin
AStream.ReadDWord();
{ Visibility }
AStream.ReadByte();
sheetstate := AStream.ReadByte(); // 0=visible, 1=hidden, 2="very" hidden
{ Sheet type }
AStream.ReadByte();
{ Sheet name: 8-bit length }
Len := AStream.ReadByte();
len := AStream.ReadByte();
{ Read string with flags }
WideName:=ReadWideString(AStream, Len, rtParams);
wideName := ReadWideString(AStream, len, rtParams);
FWorksheetNames.Add(UTF8Encode(WideName));
sheetData := TsSheetData.Create;
sheetData.Name := UTF8Encode(wideName);
sheetData.Hidden := sheetState <> 0;
FSheetList.Add(sheetdata);
end;
function TsSpreadBIFF8Reader.ReadString(const AStream: TStream;
@ -2093,8 +2102,8 @@ procedure TsSpreadBIFF8Writer.InternalWriteToStream(AStream: TStream);
const
isBIFF8 = true;
var
CurrentPos: Int64;
Boundsheets: array of Int64;
currentPos: Int64;
sheetPos: array of Int64;
i: Integer;
pane: Byte;
begin
@ -2109,9 +2118,9 @@ begin
WriteStyle(AStream);
// A BOUNDSHEET for each worksheet
SetLength(Boundsheets, Workbook.GetWorksheetCount);
SetLength(sheetPos, Workbook.GetWorksheetCount);
for i := 0 to Workbook.GetWorksheetCount - 1 do
Boundsheets[i] := WriteBoundsheet(AStream, Workbook.GetWorksheetByIndex(i).Name);
sheetPos[i] := WriteBoundsheet(AStream, Workbook.GetWorksheetByIndex(i));
WriteEXTERNBOOK(AStream);
WriteEXTERNSHEET(AStream);
@ -2126,10 +2135,10 @@ begin
{ First goes back and writes the position of the BOF of the
sheet on the respective BOUNDSHEET record }
CurrentPos := AStream.Position;
AStream.Position := Boundsheets[i];
currentPos := AStream.Position;
AStream.Position := sheetPos[i];
AStream.WriteDWord(DWordToLE(DWORD(CurrentPos)));
AStream.Position := CurrentPos;
AStream.Position := currentPos;
WriteBOF(AStream, INT_BOF_SHEET);
WriteIndex(AStream);
@ -2175,7 +2184,7 @@ begin
end;
{ Cleanup }
SetLength(Boundsheets, 0);
SetLength(sheetPos, 0);
end;
{@@ ----------------------------------------------------------------------------
@ -2285,13 +2294,15 @@ end;
@return The stream position where the absolute stream position
of the BOF of this sheet should be written (4 bytes size).
-------------------------------------------------------------------------------}
function TsSpreadBIFF8Writer.WriteBoundsheet(AStream: TStream; ASheetName: string): Int64;
function TsSpreadBIFF8Writer.WriteBoundsheet(AStream: TStream;
AWorksheet: TsWorksheet): Int64;
var
Len: Byte;
WideSheetName: WideString;
len: Byte;
wideSheetName: WideString;
sheetState: Byte;
begin
WideSheetName:=UTF8Decode(ASheetName);
Len := Length(WideSheetName);
wideSheetName := UTF8Decode(AWorksheet.Name);
len := Length(wideSheetName);
{ BIFF Record header }
WriteBIFFHeader(AStream, INT_EXCEL_ID_BOUNDSHEET, 8 + Len * Sizeof(WideChar));
@ -2302,7 +2313,8 @@ begin
AStream.WriteDWord(DWordToLE(0));
{ Visibility }
AStream.WriteByte(0);
sheetState := IfThen(soHidden in AWorksheet.Options, 1, 0);
AStream.WriteByte(sheetState);
{ Sheet type }
AStream.WriteByte(0);
@ -2311,7 +2323,7 @@ begin
AStream.WriteByte(Len);
{String flags}
AStream.WriteByte(1);
AStream.WriteBuffer(WideStringToLE(WideSheetName)[1], Len * Sizeof(WideChar));
AStream.WriteBuffer(WideStringToLE(wideSheetName)[1], len * SizeOf(WideChar));
end;
{@@ ----------------------------------------------------------------------------

View File

@ -346,6 +346,12 @@ type
function ConvertToExcelError(AValue: TsErrorValue): byte;
type
{ TsSheetData }
TsSheetData = class
Name: String;
Hidden: Boolean;
end;
{ TsBIFFHeader }
TsBIFFHeader = packed record
RecordID: Word;
@ -379,10 +385,11 @@ type
FFirstNumFormatIndexInFile: Integer;
FPalette: TsPalette;
FDefinedNames: TFPList;
FWorksheetNames: TStrings;
FWorksheetData: TFPList;
FCurSheetIndex: Integer;
FActivePane: Integer;
FExternSheets: TStrings;
FSheetList: TFPList;
procedure AddBuiltinNumFormats; override;
procedure ApplyCellFormatting(ACell: PCell; XFIndex: Word); virtual;
@ -712,7 +719,6 @@ type
TextLen: Word;
end;
function ConvertExcelDateTimeToDateTime(const AExcelDateNum: Double;
ADateMode: TDateMode): TDateTime;
begin
@ -936,6 +942,8 @@ constructor TsSpreadBIFFReader.Create(AWorkbook: TsWorkbook);
begin
inherited Create(AWorkbook);
FSheetList := TFPList.Create;
FPalette := TsPalette.Create;
PopulatePalette;
@ -967,6 +975,9 @@ begin
for j:=0 to FDefinedNames.Count-1 do TObject(FDefinedNames[j]).Free;
FDefinedNames.Free;
for j:= 0 to FSheetList.Count-1 do TObject(FSheetList[j]).Free;
FSheetList.Free;
FExternSheets.Free;
FPalette.Free;
@ -2893,8 +2904,6 @@ begin
AStream.Position := 0;
{Initializations }
FWorksheetNames := TStringList.Create;
try
FCurSheetIndex := 0;
BIFFEOF := false;
@ -2918,7 +2927,7 @@ begin
inc(FCurSheetIndex);
// It can happen in files written by Office97 that the OLE directory is
// at the end of the file.
if FCurSheetIndex = FWorksheetNames.Count then
if FCurSheetIndex = FSheetList.Count then
BIFFEOF := true;
end;
@ -2929,11 +2938,6 @@ begin
ExtractPrintRanges(sheet);
ExtractPrintTitles(sheet);
end;
finally
{ Finalization }
FreeAndNil(FWorksheetNames);
end;
end;