fpspreadsheet: Row height and column width reading/writing code for ods files complete. Test cases ok, but extremely slow speed of test application for numbertest and datetimetests. Changed units of row heights in worksheet: used to be points, is "lines" now (more consistent user interface - column width is in "standard characters", I prefer these units over centimeters because row heights/column widths become independent of screen pixels per inch this way)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3118 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2014-05-31 21:04:53 +00:00
parent 39fcfc3016
commit 33a8fdcb43
11 changed files with 952 additions and 218 deletions

View File

@ -33,7 +33,7 @@ begin
//MyWorksheet.WriteColWidth(0, 5);
//MyWorksheet.WriteColWidth(1, 30);
MyWorksheet.WriteRowHeight(0, 30); // 30 mm
MyWorksheet.WriteRowHeight(0, 3); // 3 lines
// Turn off grid lines and hide headers
//MyWorksheet.Options := MyWorksheet.Options - [soShowGridLines, soShowHeaders];
@ -367,16 +367,16 @@ begin
inc(r);
// Set width of columns 0 to 3
MyWorksheet.WriteColWidth(0, 50);
lCol.Width := 15;
MyWorksheet.WriteColWidth(0, 48); // 48 characters, default is 12 --> 4x default width
lCol.Width := 24; // 24 characters, default is 12 --> 2x default width
MyWorksheet.WriteColInfo(1, lCol);
MyWorksheet.WriteColInfo(2, lCol);
MyWorksheet.WriteColInfo(3, lCol);
// Set height of rows 5 and 6
lRow.Height := 10;
lRow.Height := 4; // 4 lines
MyWorksheet.WriteRowInfo(5, lRow);
lRow.Height := 5;
lRow.Height := 2; // 2 lines
MyWorksheet.WriteRowInfo(6, lRow);
// Save the spreadsheet to a file

View File

@ -45,7 +45,7 @@ begin
MyWorkbook.AddFont('Calibri', 20, [], scRed);
// Change row height
MyWorksheet.WriteRowHeight(0, 20); // modify height of row 0 to 20 mm
MyWorksheet.WriteRowHeight(0, 1.1); // modify height of row 0 to 3 lines
// Change colum widths
MyWorksheet.WriteColWidth(0, 40);

View File

@ -383,7 +383,7 @@ begin
MyWorksheet.WriteColInfo(5, lCol);
// Set height of rows 0
MyWorksheet.WriteRowHeight(0, 30); // 30 mm
MyWorksheet.WriteRowHeight(0, 5); // 5 lines
// Creates a new worksheet
MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet2);

View File

@ -32,6 +32,7 @@ begin
MyWorksheet.WriteUTF8Text(4, 2, 'Total:');// C5
MyWorksheet.WriteNumber(4, 3, 10); // D5
MyWorksheet.WriteDateTime(5, 0, now);
// Add some formatting
MyWorksheet.WriteUsedFormatting(0, 0, [uffBold]);

File diff suppressed because it is too large Load Diff

View File

@ -335,16 +335,22 @@ type
PCell = ^TCell;
const
// Takes account of effect of cell margins on row height by adding this
// value to the nominal row height. Note that this is an empirical value and may be wrong.
ROW_HEIGHT_CORRECTION = 0.2;
type
TRow = record
Row: Cardinal;
Height: Single; // in millimeters
Height: Single; // in "lines"
end;
PRow = ^TRow;
TCol = record
Col: Cardinal;
Width: Single; // in "characters". Excel uses the with of char "0" in 1st font
Width: Single; // in "characters". Excel uses the width of char "0" in 1st font
end;
PCol = ^TCol;
@ -368,7 +374,7 @@ type
FWorkbook: TsWorkbook;
FCells: TAvlTree; // Items are TCell
FCurrentNode: TAVLTreeNode; // For GetFirstCell and GetNextCell
FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from the standard
FRows, FCols: TIndexedAVLTree; // This lists contain only rows or cols with styles different from default
FLeftPaneWidth: Integer;
FTopPaneHeight: Integer;
FOptions: TsSheetOptions;
@ -475,8 +481,12 @@ type
{ Data manipulation methods - For Rows and Cols }
function FindRow(ARow: Cardinal): PRow;
function FindCol(ACol: Cardinal): PCol;
function GetCellCountInRow(ARow: Cardinal): Cardinal;
function GetCellCountInCol(ACol: Cardinal): Cardinal;
function GetRow(ARow: Cardinal): PRow;
function GetRowHeight(ARow: Cardinal): Single;
function GetCol(ACol: Cardinal): PCol;
function GetColWidth(ACol: Cardinal): Single;
procedure RemoveAllRows;
procedure RemoveAllCols;
procedure WriteRowInfo(ARow: Cardinal; AData: TRow);
@ -511,10 +521,15 @@ type
FBuiltinFontCount: Integer;
FPalette: array of TsColorValue;
FReadFormulas: Boolean;
FDefaultColWidth: Single; // in "characters". Excel uses the width of char "0" in 1st font
FDefaultRowHeight: Single; // in "character heights", i.e. line count
{ Internal methods }
procedure RemoveWorksheetsCallback(data, arg: pointer);
public
FormatSettings: TFormatSettings;
{ Base methods }
constructor Create;
destructor Destroy; override;
@ -530,6 +545,7 @@ type
const AOverwriteExisting: Boolean = False); overload;
procedure WriteToFile(const AFileName: String; const AOverwriteExisting: Boolean = False); overload;
procedure WriteToStream(AStream: TStream; AFormat: TsSpreadsheetFormat);
{ Worksheet list handling methods }
function AddWorksheet(AName: string): TsWorksheet;
function GetFirstWorksheet: TsWorksheet;
@ -537,6 +553,7 @@ type
function GetWorksheetByName(AName: String): TsWorksheet;
function GetWorksheetCount: Cardinal;
procedure RemoveAllWorksheets;
{ Font handling }
function AddFont(const AFontName: String; ASize: Single;
AStyle: TsFontStyles; AColor: TsColor): Integer; overload;
@ -544,11 +561,13 @@ type
procedure CopyFontList(ASource: TFPList);
function FindFont(const AFontName: String; ASize: Single;
AStyle: TsFontStyles; AColor: TsColor): Integer;
function GetDefaultFontSize: Single;
function GetFont(AIndex: Integer): TsFont;
function GetFontCount: Integer;
procedure InitFonts;
procedure RemoveAllFonts;
procedure SetDefaultFont(const AFontName: String; ASize: Single);
{ Color handling }
function AddColorToPalette(AColorValue: TsColorValue): TsColor;
function FPSColorToHexString(AColor: TsColor; ARGBColor: TFPColor): String;
@ -560,6 +579,13 @@ type
procedure UseDefaultPalette;
procedure UsePalette(APalette: PsPalette; APaletteCount: Word;
ABigEndian: Boolean = false);
{@@ The default column width given in "character units" (width of the
character "0" in the default font) }
property DefaultColWidth: Single read FDefaultColWidth;
{@@ The default row height is given in "line count" (height of the
default font }
property DefaultRowHeight: Single read FDefaultRowHeight;
{@@ This property is only used for formats which don't support unicode
and support a single encoding for the whole document, like Excel 2 to 5 }
property Encoding: TsEncoding read FEncoding write FEncoding;
@ -1366,6 +1392,7 @@ end;
function TsWorksheet.GetLastColIndex: Cardinal;
var
AVLNode: TAVLTreeNode;
i: Integer;
begin
Result := 0;
@ -1378,6 +1405,12 @@ begin
Result := Math.Max(Result, PCell(AVLNode.Data)^.Col);
AVLNode := FCells.FindSuccessor(AVLNode);
end;
// In addition, there may be column records defining the column width even
// without content
for i:=0 to FCols.Count-1 do
if FCols[i] <> nil then
Result := Math.Max(Result, PCol(FCols[i])^.Col);
end;
function TsWorksheet.GetLastColNumber: Cardinal;
@ -1424,12 +1457,18 @@ end;
function TsWorksheet.GetLastRowIndex: Cardinal;
var
AVLNode: TAVLTreeNode;
i: Integer;
begin
Result := 0;
AVLNode := FCells.FindHighest;
if Assigned(AVLNode) then
Result := PCell(AVLNode.Data).Row;
// In addition, there may be row records even for empty rows.
for i:=0 to FRows.Count-1 do
if FRows[i] <> nil then
Result := Math.Max(Result, PRow(FRows[i])^.Row);
end;
function TsWorksheet.GetLastRowNumber: Cardinal;
@ -2243,7 +2282,6 @@ var
AVLNode: TAVGLVLTreeNode;
begin
Result := nil;
LElement.Row := ARow;
AVLNode := FRows.Find(@LElement);
if Assigned(AVLNode) then
@ -2256,7 +2294,6 @@ var
AVLNode: TAVGLVLTreeNode;
begin
Result := nil;
LElement.Col := ACol;
AVLNode := FCols.Find(@LElement);
if Assigned(AVLNode) then
@ -2285,6 +2322,72 @@ begin
end;
end;
{ Counts how many cells exist in the given column. Blank cells do contribute
to the sum, as well as rows with a non-default style. }
function TsWorksheet.GetCellCountInCol(ACol: Cardinal): Cardinal;
var
cell: PCell;
r: Cardinal;
row: PRow;
begin
Result := 0;
for r := 0 to GetLastRowIndex do begin
cell := FindCell(r, ACol);
if cell <> nil then
inc(Result)
else begin
row := FindRow(r);
if row <> nil then inc(Result);
end;
end;
end;
{ Counts how many cells exist in the given row. Blank cells do contribute
to the sum, as well as columns with a non-default style. }
function TsWorksheet.GetCellCountInRow(ARow: Cardinal): Cardinal;
var
cell: PCell;
c: Cardinal;
col: PCol;
begin
Result := 0;
for c := 0 to GetLastColIndex do begin
cell := FindCell(ARow, c);
if cell <> nil then
inc(Result)
else begin
col := FindCol(c);
if col <> nil then inc(Result);
end;
end;
end;
{ Returns the width of the given column. If there is no column record then
the default column width is returned. }
function TsWorksheet.GetColWidth(ACol: Cardinal): Single;
var
col: PCol;
begin
col := FindCol(ACol);
if col <> nil then
Result := col^.Width
else
Result := FWorkbook.DefaultColWidth;
end;
{ Returns the height of the given row. If there is no row record then the
default row height is returned }
function TsWorksheet.GetRowHeight(ARow: Cardinal): Single;
var
row: PRow;
begin
row := FindRow(ARow);
if row <> nil then
Result := row^.Height
else
Result := FWorkbook.DefaultRowHeight;
end;
procedure TsWorksheet.RemoveAllRows;
var
Node: Pointer;
@ -2359,6 +2462,8 @@ constructor TsWorkbook.Create;
begin
inherited Create;
FWorksheets := TFPList.Create;
FDefaultColWidth := 12;
FDefaultRowHeight := 1;
FormatSettings := DefaultFormatSettings;
FFontList := TFPList.Create;
SetDefaultFont('Arial', 10.0);
@ -2777,7 +2882,6 @@ begin
// FONT4 which does not exist in BIFF is added automatically with nil as place-holder
AddFont(fntName, fntSize, [fssBold, fssItalic], scBlack); // FONT5 for uffBoldItalic
FBuiltinFontCount := FFontList.Count;
end;
@ -2816,6 +2920,14 @@ begin
end;
end;
{@@
Returns the point size of the default font
}
function TsWorkbook.GetDefaultFontSize: Single;
begin
Result := GetFont(0).Size;
end;
{@@
Returns the font with the given index.
}

View File

@ -525,10 +525,13 @@ begin
Result := h;
end;
{ Converts the row height, given in mm, to pixels }
{ Converts the row height (from a worksheet row), given in lines, to pixels }
function TsCustomWorksheetGrid.CalcRowHeight(AHeight: Single): Integer;
var
h_pts: Single;
begin
Result := round(AHeight / 25.4 * Screen.PixelsPerInch) + 4;
h_pts := AHeight * (Workbook.GetFont(0).Size + ROW_HEIGHT_CORRECTION);
Result := PtsToPX(h_pts, Screen.PixelsPerInch) + 4;
end;
procedure TsCustomWorksheetGrid.ChangedCellHandler(ASender: TObject; ARow, ACol:Cardinal);
@ -1871,7 +1874,7 @@ end;
procedure TsCustomWorksheetGrid.HeaderSized(IsColumn: Boolean; index: Integer);
var
w0: Integer;
h: Single;
h, h_pts: Single;
begin
if FWorksheet = nil then
exit;
@ -1884,8 +1887,9 @@ begin
FWorksheet.WriteColWidth(GetWorksheetCol(Index), ColWidths[Index] div w0);
end else begin
// The grid's row heights are in "pixels", the worksheet's row heights are
// in millimeters.
h := (RowHeights[Index] - 4) / Screen.PixelsPerInch * 25.4;
// in "lines"
h_pts := PxToPts(RowHeights[Index] - 4, Screen.PixelsPerInch); // in points
h := h_pts / (FWorkbook.GetFont(0).Size + ROW_HEIGHT_CORRECTION);
FWorksheet.WriteRowHeight(GetWorksheetRow(Index), h);
end;
end;
@ -2616,6 +2620,7 @@ end;
initialization
fpsutils.ScreenPixelsPerInch := Screen.PixelsPerInch;
finalization
FreeAndNil(FillPattern_BIFF2);

View File

@ -66,9 +66,6 @@ function GetErrorValueStr(AErrorValue: TsErrorValue): String;
function UTF8TextToXMLText(AText: ansistring): ansistring;
function TwipsToMillimeters(AValue: Integer): Single;
function MillimetersToTwips(AValue: Single): Integer;
function IfThen(ACondition: Boolean; AValue1,AValue2: TsNumberFormat): TsNumberFormat; overload;
function IsDateTimeFormat(AFormat: TsNumberFormat): Boolean;
@ -102,12 +99,24 @@ function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
function FormatDateTime(const FormatStr: string; DateTime: TDateTime;
const FormatSettings: TFormatSettings; Options : TFormatDateTimeOptions = []): string;
function TwipsToPts(AValue: Integer): Single;
function PtsToTwips(AValue: Single): Integer;
function cmToPts(AValue: Double): Double;
function PtsToCm(AValue: Double): Double;
function InToPts(AValue: Double): Double;
function mmToPts(AValue: Double): Double;
function PtsToMM(AValue: Double): Double;
function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double;
function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer;
function HTMLLengthStrToPts(AValue: String): Double;
//function HMTLLengthStrToPts(AValue: String): Double;
function HTMLColorStrToColor(AValue: String): TsColorValue;
function ColorToHTMLColorStr(AValue: TsColorValue): String;
var
ScreenPixelsPerInch: Integer = 96;
implementation
uses
@ -533,19 +542,6 @@ begin
Result:=WrkStr;
end;
{ Excel's unit of row heights is "twips", i.e. 1/20 point. 72 pts = 1 inch = 25.4 mm
The procedure TwipsToMillimeters performs the conversion to millimeters. }
function TwipsToMillimeters(AValue: Integer): Single;
begin
Result := 25.4 * AValue / (20 * 72);
end;
{ Converts Millimeters to Twips, i.e. 1/20 pt }
function MillimetersToTwips(AValue: Single): Integer;
begin
Result := Round((AValue * 20 * 72) / 25.4);
end;
{ Returns either AValue1 or AValue2, depending on the condition.
For reduciton of typing... }
function IfThen(ACondition: Boolean; AValue1, AValue2: TsNumberFormat): TsNumberFormat;
@ -1296,16 +1292,82 @@ begin
DateTimeToString(Result, FormatStr, DateTime, FormatSettings,Options);
end;
{ Excel's unit of row heights is "twips", i.e. 1/20 point.
Converts Twips to points. }
function TwipsToPts(AValue: Integer): Single;
begin
Result := AValue / 20;
end;
{ Converts points to twips (1 twip = 1/20 point) }
function PtsToTwips(AValue: Single): Integer;
begin
Result := round(AValue * 20);
end;
{ Converts centimeters to points (72 pts = 1 inch) }
function cmToPts(AValue: Double): Double;
begin
Result := AValue/2.54*72;
Result := AValue * 72 / 2.54;
end;
{ Converts points to centimeters }
function PtsToCm(AValue: Double): Double;
begin
Result := AValue / 72 * 2.54;
end;
{ Converts inches to points (72 pts = 1 inch) }
function InToPts(AValue: Double): Double;
begin
Result := AValue * 72;
end;
{ Converts millimeters to points (72 pts = 1 inch) }
function mmToPts(AValue: Double): Double;
begin
Result := AValue/25.4*72;
Result := AValue * 72 / 25.4;
end;
{ Converts points to millimeters }
function PtsToMM(AValue: Double): Double;
begin
Result := AValue / 72 * 25.4;
end;
{ Converts pixels to points. }
function pxToPts(AValue, AScreenPixelsPerInch: Integer): Double;
begin
Result := (AValue / AScreenPixelsPerInch) * 72;
end;
{ Converts points to pixels }
function PtsToPx(AValue: Double; AScreenPixelsPerInch: Integer): Integer;
begin
Result := Round(AValue / 72 * AScreenPixelsPerInch);
end;
{ converts a HTML length string to points. The units are assumed to be the last
two digits of the string }
function HTMLLengthStrToPts(AValue: String): Double;
var
units: String;
x: Double;
res: Word;
begin
units := lowercase(Copy(AValue, Length(AValue)-1, 2));
val(copy(AValue, 1, Length(AValue)-2), x, res);
// No hasseling with the decimal point...
if units = 'in' then
Result := InToPts(x)
else if units = 'cm' then
Result := cmToPts(x)
else if units = 'mm' then
Result := mmToPts(x)
else if units = 'px' then
Result := pxToPts(Round(x), ScreenPixelsPerInch)
else
raise Exception.Create('Unknown length units');
end;
{ converts a HTML color string to a TsColorValue. For ods }

View File

@ -107,6 +107,8 @@ type
procedure TestWriteRead_ODS_Alignment;
procedure TestWriteRead_ODS_Border;
procedure TestWriteRead_ODS_BorderStyles;
procedure TestWriteRead_ODS_ColWidths;
procedure TestWriteRead_ODS_RowHeights;
procedure TestWriteRead_ODS_TextRotation;
procedure TestWriteRead_ODS_WordWrap;
end;
@ -203,13 +205,13 @@ begin
end;
// Column width
SollColWidths[0] := 20; // characters based on width of "0"
SollColWidths[0] := 20; // characters based on width of "0" of default font
SollColWidths[1] := 40;
// Row heights
SollRowHeights[0] := 5;
SollRowHeights[1] := 10;
SollRowHeights[2] := 50;
SollRowHeights[0] := 1; // Lines of default font
SollRowHeights[1] := 2;
SollRowHeights[2] := 4;
// Cell borders
SollBorders[0] := [];
@ -723,6 +725,7 @@ begin
MyWorkSheet:= MyWorkBook.AddWorksheet(ColWidthSheet);
for Col := Low(SollColWidths) to High(SollColWidths) do begin
lCol.Width := SollColWidths[Col];
//MyWorksheet.WriteNumber(0, Col, 1);
MyWorksheet.WriteColInfo(Col, lCol);
end;
MyWorkBook.WriteToFile(TempFile, AFormat, true);
@ -742,6 +745,7 @@ begin
if lpCol = nil then
fail('Error in test code. Failed to return saved column width');
ActualColWidth := lpCol^.Width;
if abs(SollColWidths[Col] - ActualColWidth) > 1E-2 then // take rounding errors into account
CheckEquals(SollColWidths[Col], ActualColWidth,
'Test saved colwidth mismatch, column '+ColNotation(MyWorkSheet,Col));
end;
@ -766,6 +770,10 @@ begin
TestWriteReadColWidths(sfExcel8);
end;
procedure TSpreadWriteReadFormatTests.TestWriteRead_ODS_ColWidths;
begin
TestWriteReadColWidths(sfOpenDocument);
end;
{ --- Row height tests --- }
@ -801,13 +809,10 @@ begin
if MyWorksheet=nil then
fail('Error in test code. Failed to get named worksheet');
for Row := Low(SollRowHeights) to High(SollRowHeights) do begin
lpRow := MyWorksheet.GetRow(Row);
if lpRow = nil then
fail('Error in test code. Failed to return saved row height');
// Rounding to twips in Excel would cause severe rounding error if we'd compare millimeters
// --> go back to twips
ActualRowHeight := MillimetersToTwips(lpRow^.Height);
CheckEquals(MillimetersToTwips(SollRowHeights[Row]), ActualRowHeight,
ActualRowHeight := MyWorksheet.GetRowHeight(Row);
// Take care of rounding errors
if abs(ActualRowHeight - SollRowHeights[Row]) > 1e-2 then
CheckEquals(SollRowHeights[Row], ActualRowHeight,
'Test saved row height mismatch, row '+RowNotation(MyWorkSheet,Row));
end;
// Finalization
@ -831,6 +836,11 @@ begin
TestWriteReadRowHeights(sfExcel8);
end;
procedure TSpreadWriteReadFormatTests.TestWriteRead_ODS_RowHeights;
begin
TestWriteReadRowHeights(sfOpenDocument);
end;
{ --- Text rotation tests --- }

View File

@ -708,7 +708,12 @@ begin
if h and $8000 = 0 then begin // if this bit were set, rowheight would be default
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
// Row height is encoded into the 15 remaining bits in units "twips" (1/20 pt)
lRow^.Height := TwipsToMillimeters(h and $7FFF);
// We need it in "lines" units.
lRow^.Height := TwipsToPts(h and $7FFF) / Workbook.GetFont(0).Size;
if lRow^.Height > ROW_HEIGHT_CORRECTION then
lRow^.Height := lRow^.Height - ROW_HEIGHT_CORRECTION
else
lRow^.Height := 0;
end;
end;
@ -1632,6 +1637,7 @@ var
containsXF: Boolean;
rowheight: Word;
w: Word;
h: Single;
begin
containsXF := false;
@ -1649,10 +1655,14 @@ begin
AStream.WriteWord(WordToLE(Word(ALastColIndex) + 1));
{ Row height (in twips, 1/20 point) and info on custom row height }
if (ARow = nil) or (ARow^.Height = 0) then
rowheight := round(Workbook.GetFont(0).Size*20)
h := Workbook.GetFont(0).Size;
if (ARow = nil) or (ARow^.Height = Workbook.DefaultRowHeight) then
rowheight := PtsToTwips((Workbook.DefaultRowHeight + ROW_HEIGHT_CORRECTION) * h)
else
rowheight := MillimetersToTwips(ARow^.Height);
if (ARow^.Height = 0) then
rowheight := 0
else
rowheight := PtsToTwips((ARow^.Height + ROW_HEIGHT_CORRECTION) * h);
w := rowheight and $7FFF;
AStream.WriteWord(WordToLE(w));

View File

@ -1329,12 +1329,13 @@ begin
if h and $8000 = 0 then begin // if this bit were set, rowheight would be default
lRow := FWorksheet.GetRow(WordLEToN(rowrec.RowIndex));
// Row height is encoded into the 15 remaining bits in units "twips" (1/20 pt)
lRow^.Height := TwipsToMillimeters(h and $7FFF);
end else
// We need it in "lines", i.e. we divide the points by the point size of the default font
lRow^.Height := TwipsToPts(h and $7FFF) / FWorkbook.GetFont(0).Size;
if lRow^.Height > ROW_HEIGHT_CORRECTION then
lRow^.Height := lRow^.Height - ROW_HEIGHT_CORRECTION
else
lRow^.Height := 0;
//lRow^.AutoHeight := rowrec.Flags and $00000040 = 0;
// If this bit is set row height does not change with font height, i.e. has been
// changed manually.
end;
end;
{ Reads the cell address used in an RPN formula element. Evaluates the corresponding
@ -1903,6 +1904,7 @@ var
spaceabove, spacebelow: Boolean;
colindex: Cardinal;
rowheight: Word;
h: Single;
begin
// Check for additional space above/below row
spaceabove := false;
@ -1934,10 +1936,14 @@ begin
AStream.WriteWord(WordToLE(Word(ALastColIndex) + 1));
{ Row height (in twips, 1/20 point) and info on custom row height }
if (ARow = nil) or (ARow^.Height = 0) then
rowheight := round(Workbook.GetFont(0).Size*20)
h := Workbook.GetFont(0).Size; // Point size of default font
if (ARow = nil) or (ARow^.Height = Workbook.DefaultRowHeight) then
rowheight := PtsToTwips((Workbook.DefaultRowHeight + ROW_HEIGHT_CORRECTION) * h)
else
rowheight := MillimetersToTwips(ARow^.Height);
if (ARow^.Height = 0) then
rowheight := 0
else
rowheight := PtsToTwips((ARow^.Height + ROW_HEIGHT_CORRECTION)*h);
w := rowheight and $7FFF;
AStream.WriteWord(WordToLE(w));