lazarus-ccr/applications/biffexplorer/beutils.pas
2016-02-21 17:42:13 +00:00

189 lines
4.9 KiB
ObjectPascal

unit beUtils;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, IniFiles, Forms,
fpstypes, fpspreadsheet;
function CreateIni : TCustomIniFile;
procedure ReadFormFromIni(ini: TCustomIniFile; ASection: String; AForm: TCustomForm);
procedure WriteFormToIni(ini: TCustomIniFile; ASection: String; AForm: TCustomForm);
function GetFileFormatName(AFormat: TsSpreadsheetFormat): String;
function GetFormatFromFileHeader(const AFileName: TFileName;
out SheetType: TsSpreadsheetFormat): Boolean;
function GetFixedFontName: String;
implementation
uses
uvirtuallayer_ole;
function CreateIni : TCustomIniFile;
var
cfg : string;
begin
cfg := GetAppConfigDir(false);
if not DirectoryExists(cfg) then
CreateDir(cfg);
result := TMemIniFile.Create(GetAppConfigFile(false));
end;
procedure ReadFormFromIni(ini: TCustomIniFile; ASection: String; AForm: TCustomForm);
var
L,T,W,H: Integer;
isMax: Boolean;
begin
L := ini.ReadInteger(ASection, 'Left', AForm.Left);
T := Ini.ReadInteger(ASection, 'Top', AForm.Top);
W := ini.ReadInteger(ASection, 'Width', AForm.Width);
H := ini.ReadInteger(ASection, 'Height', AForm.Height);
isMax := ini.ReadBool(ASection, 'Maximized', AForm.WindowState = wsMaximized);
if W > Screen.Width then W := Screen.Width;
if H > Screen.Height then H := Screen.Height;
if L < 0 then L := 0;
if T < 0 then T := 0;
if L + W > Screen.Width then L := Screen.Width - W;
if T + H > Screen.Height then T := Screen.Height - H;
AForm.Left := L;
AForm.Top := T;
AForm.Width := W;
AForm.Height := H;
if IsMax then
AForm.WindowState := wsMaximized
else
AForm.WindowState := wsNormal;
end;
procedure WriteFormToIni(ini: TCustomIniFile; ASection: String; AForm: TCustomForm);
begin
ini.WriteBool(ASection, 'Maximized', (AForm.WindowState = wsMaximized));
if AForm.WindowState = wsNormal then begin
ini.WriteInteger(ASection, 'Left', AForm.Left);
ini.WriteInteger(ASection, 'Top', AForm.Top);
ini.WriteInteger(ASection, 'Width', AForm.Width);
ini.WriteInteger(ASection, 'Height', AForm.Height);
end;
end;
function GetFileFormatName(AFormat: TsSpreadsheetFormat): string;
begin
case AFormat of
sfExcel2 : Result := 'BIFF2';
{ Excel3/4 not supported fpspreadsheet
sfExcel3 : Result := 'BIFF3';
sfExcel4 : Result := 'BIFF4';
}
sfExcel5 : Result := 'BIFF5';
sfExcel8 : Result := 'BIFF8';
sfooxml : Result := 'OOXML';
sfOpenDocument : Result := 'Open Document';
sfCSV : Result := 'CSV';
sfWikiTable_Pipes : Result := 'WikiTable Pipes';
sfWikiTable_WikiMedia : Result := 'WikiTable WikiMedia';
else Result := '-unknown format-';
end;
end;
function GetFormatFromFileHeader(const AFileName: TFileName;
out SheetType: TsSpreadsheetFormat): Boolean;
const
BIFF2_HEADER: array[0..3] of byte = (
$09,$00, $04,$00); // they are common to all BIFF2 files that I've seen
BIFF58_HEADER: array[0..7] of byte = (
$D0,$CF, $11,$E0, $A1,$B1, $1A,$E1);
function ValidOLEStream(AStream: TStream; AName: String): Boolean;
var
fsOLE: TVirtualLayer_OLE;
begin
AStream.Position := 0;
fsOLE := TVirtualLayer_OLE.Create(AStream);
try
fsOLE.Initialize;
Result := fsOLE.FileExists('/'+AName);
finally
fsOLE.Free;
end;
end;
var
buf: packed array[0..7] of byte = (0,0,0,0,0,0,0,0);
stream: TStream;
i: Integer;
ok: Boolean;
begin
Result := false;
stream := TFileStream.Create(AFileName, fmOpenRead + fmShareDenyNone);
try
// Read first 8 bytes
stream.ReadBuffer(buf, 8);
// Check for Excel 2
ok := true;
for i:=0 to High(BIFF2_HEADER) do
if buf[i] <> BIFF2_HEADER[i] then
begin
ok := false;
break;
end;
if ok then
begin
SheetType := sfExcel2;
Exit(True);
end;
// Check for Excel 5 or 8
for i:=0 to High(BIFF58_HEADER) do
if buf[i] <> BIFF58_HEADER[i] then
exit;
// Now we know that the file is a Microsoft compound document.
// We check for Excel 5 in which the stream is named "Book"
if ValidOLEStream(stream, 'Book') then begin
SheetType := sfExcel5;
exit(True);
end;
// Now we check for Excel 8 which names the stream "Workbook"
if ValidOLEStream(stream, 'Workbook') then begin
SheetType := sfExcel8;
exit(True);
end;
finally
stream.Free;
end;
end;
function GetFixedFontName: String;
var
idx: Integer;
begin
Result := Screen.SystemFont.Name;
idx := Screen.Fonts.IndexOf('Courier New');
if idx = -1 then
idx := Screen.Fonts.IndexOf('Courier 10 Pitch');
if idx <> -1 then
Result := Screen.Fonts[idx]
else
for idx := 0 to Screen.Fonts.Count-1 do
if pos('courier', Lowercase(Screen.Fonts[idx])) = 1 then
begin
Result := Screen.Fonts[idx];
exit;
end;
end;
end.