unit QExport4ODS;

{$I QExport4VerCtrl.inc}

interface

uses
  {$IFDEF VCL16}
    System.Classes,
    Vcl.Graphics,
  {$ELSE}
    Classes,
    Graphics,
  {$ENDIF}
  QExport4,
  QExport4IniFiles,
  QExport4BaseODFClass,
  QExport4Types;

type
  TQExportODSOptions = class(TPersistent)
  private
    FHolder: TPersistent;
    FHeaderStyle: TODSCellParagraphStyle;
    FFooterStyle: TODSCellParagraphStyle;
    FCaptionRowStyle: TODSCellParagraphStyle;
    FDataStyle: TODSCellParagraphStyle;
    FStripStyle: TODFStripStyleType;
    FStripStylesList: TODSStylesList;
    FFontList: TStrings;

    procedure SetHeaderStyle(const Value: TODSCellParagraphStyle);
    procedure SetFooterStyle(const Value: TODSCellParagraphStyle);
    procedure SetCaptionStyle(const Value: TODSCellParagraphStyle);
    procedure SetDataStyle(const Value: TODSCellParagraphStyle);
    procedure SetStripStyles(const Value: TODSStylesList);
  protected
    function GetOwner: TPersistent; override;
  public
    constructor Create(Holder: TPersistent);
    destructor Destroy; override;
    procedure Assign(Source: TPersistent); override;
    function CheckFontInList(FontName: string): Boolean;

    property FontList: TStrings read FFontList write FFontList;
  published
    property HeaderStyle: TODSCellParagraphStyle read FHeaderStyle
      write SetHeaderStyle;
    property FooterStyle: TODSCellParagraphStyle read FFooterStyle
      write SetFooterStyle;
    property CaptionRowStyle: TODSCellParagraphStyle read FCaptionRowStyle
      write SetCaptionStyle;
    property DataStyle: TODSCellParagraphStyle read FDataStyle
      write SetDataStyle;
    property StripStyle: TODFStripStyleType read FStripStyle write FStripStyle
      default sstNone;
    property StripStylesList: TODSStylesList read FStripStylesList
      write SetStripStyles;
  end;

  TQExport4ODS = class(TQExport4AdvancedText)
  private
    FODSFile: TBaseODFFile;
    FTableName: String;
    FODSOptions: TQExportODSOptions;
    FRowCounter: Integer;
    function ColorToString(Color: TColor): string;
    function PointsToCms(Value: Integer): string;
    procedure SetOptions(const Value: TQExportODSOptions);
  protected
    procedure BeginExport; override;

    procedure EndExport; override;
    procedure WriteDataRow; override;
    procedure WriteCaptionRow; override;
    procedure AddStyles;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure Execute; override;
    property ODSFile: TBaseODFFile read FODSFile write FODSFile;

  published
    property AllowCaptions;
    property Captions;
    property UserFormats;
    property SheetName: String read FTableName write FTableName;
    property ODSOptions: TQExportODSOptions read FODSOptions write SetOptions;
  end;

implementation

uses
  {$IFDEF VCL16}
    System.SysUtils,
    System.Variants,
  {$ELSE}
    SysUtils,
    {$IFDEF VCL6}
      Variants,
    {$ENDIF}
  {$ENDIF}
  {$IFDEF VCL17}
    System.UITypes,
  {$ENDIF}
  QExport4StrIDs,
  QExport4Common,
  QExport4EmsWideStrUtils;


{ TQExport4ODS }

procedure TQExport4ODS.AddStyles;
var
  I: Integer;

  procedure WriteFontStyleNode(TypeOfOptions: Integer);

    procedure SubRoutine(TempPar: TODSCellParagraphStyle);
    begin
      ODSFile.WriteSpecificNode(20, '', ['style:name', 'svg:font-family',
        'style:font-pitch'], [TempPar.Font.Name, TempPar.Font.Name, 'variable']);
      ODSOptions.FontList.Add(TempPar.Font.Name);
    end;

  begin
    if (TypeOfOptions = 0) then
      if not (ODSOptions.CheckFontInList('Arial')) then
      begin
        ODSFile.WriteSpecificNode(20, '', ['style:name', 'svg:font-family',
          'style:font-pitch'], ['Arial', 'Arial', 'variable']);
        ODSOptions.FontList.Add('Arial');
      end;
    if (TypeOfOptions = 1) then
      if not (ODSOptions.CheckFontInList(ODSOptions.HeaderStyle.Font.Name)) then
        SubRoutine(ODSOptions.HeaderStyle);
    if (TypeOfOptions = 2) then
      if not (ODSOptions.CheckFontInList(ODSOptions.FooterStyle.Font.Name)) then
        SubRoutine(ODSOptions.FooterStyle);
    if (TypeOfOptions = 3) then
      if not (ODSOptions.CheckFontInList(ODSOptions.CaptionRowStyle.Font.Name)) then
        SubRoutine(ODSOptions.CaptionRowStyle);
    if (TypeOfOptions = 4) then
      if not (ODSOptions.CheckFontInList(ODSOptions.DataStyle.Font.Name)) then
        SubRoutine(ODSOptions.DataStyle);
    if (TypeOfOptions > 4) then
      if not (ODSOptions.CheckFontInList(
        ODSOptions.StripStylesList[TypeOfOptions - 5].Font.Name)) then
          SubRoutine(ODSOptions.StripStylesList[TypeOfOptions - 5]);
  end;

  procedure WriteCellStyleNode(TypeOfOptions: Integer);

    procedure SubRoutine(TempPar: TODSCellParagraphStyle; Name: WideString;
      Border: TODFBorder);
    var
      AttList, AttValues: array of WideString;
      Num: integer;
    begin
      //Common style declaring section
      ODSFile.WriteSpecificNode(21, '', ['style:name',
        'style:family', 'style:parent-style-name'], [Name, 'table-cell', 'Default']);
      SetLength(AttList, 3);
      SetLength(AttValues, 3);
      AttList[0] := 'style:font-name';
      AttList[1] := 'fo:font-size';
      AttList[2] := 'fo:color';
      AttValues[0] := TempPar.Font.Name;
      AttValues[1] := IntToStr(TempPar.Font.Size) + 'pt';
      AttValues[2] := ColorToString(TempPar.Font.Color);
      if (fsItalic in TempPar.Font.Style) then
      begin
        Num := Length(AttValues);
        SetLength(AttList, Num + 1);
        SetLength(AttValues, Num + 1);
        AttList[Num] := 'fo:font-style';
        AttValues[Num] := 'italic';
      end;
      if (fsBold in TempPar.Font.Style) then
      begin
        Num := Length(AttValues);
        SetLength(AttList, Num + 1);
        SetLength(AttValues, Num + 1);
        AttList[Num] := 'fo:font-weight';
        AttValues[Num] := 'bold';
      end;
      if (fsUnderline in TempPar.Font.Style) then
      begin
        Num := Length(AttValues);
        SetLength(AttList, Num + 3);
        SetLength(AttValues, Num + 3);
        AttList[Num] := 'style:text-underline-style';
        AttValues[Num] := 'solid';
        AttList[Num + 1] := 'text-underline-width';
        AttValues[Num + 1] := 'auto';
        AttList[Num + 2] :='style:text-underline-color';
        AttValues[Num + 2] := 'font-color';
      end;
      if (fsStrikeOut in TempPar.Font.Style) then
      begin
        Num := Length(AttValues);
        SetLength(AttList, Num + 1);
        SetLength(AttValues, Num + 1);
        AttList[Num] := 'style:text-line-through-style';
        AttValues[Num] := 'solid';
      end;
      ODSFile.WriteSpecificNode(26, '', AttList, AttValues);

      case TempPar.Alignment of
        taODFLeft:
          ODSFile.WriteSpecificNode(29, '', ['fo:text-align'], ['start']);
        taODFRight:
          ODSFile.WriteSpecificNode(29, '', ['fo:text-align'], ['end']);
        taODFCenter:
          ODSFile.WriteSpecificNode(29, '', ['fo:text-align'], ['center']);
        taODFJustify:
          ODSFile.WriteSpecificNode(29, '', ['fo:text-align'], ['justify']);
      end;

      SetLength(AttList, 4);
      SetLength(AttValues, 4);
      AttList[0] := 'style:text-align-source';
      AttList[1] := 'style:repeat-content';
      AttValues[0] := 'fix';
      AttValues[1] := 'false';
      AttList[2] := 'fo:border';
      AttList[3] := 'style:vertical-align';
      if (Border.BorderStyle = bsODFSolid) then
        AttValues[2] := PointsToCms(Border.BorderWidth) +
            ' ' + 'solid' + ' ' + ColorToString(Border.BorderColor)
      else
        AttValues[2] := 'none';
      case TempPar.VerticalAligment of
        taODFTop:
          AttValues[3] := 'top';
        taODFMiddle:
          AttValues[3] := 'middle';
        taODFBottom:
          AttValues[3] := 'bottom';
      end;
      if (TempPar.AllowBackground) then
      begin
        SetLength(AttList, 5);
        SetLength(AttValues, 5);
        AttList[4] := 'fo:background-color';
        AttValues[4] := ColorToString(TempPar.BackgroundColor);
      end;
      ODSFile.WriteSpecificNode(25, '', AttList, AttValues);
      ODSFile.WriteSpecificNode(1021, '', [], []);
    end;
  begin
    //Default Table Style
    if (TypeOfOptions = -3) then
    begin
      ODSFile.WriteSpecificNode(21, '', ['style:name', 'style:family'],
        ['DefaultTableStyle', 'table']);
      ODSFile.WriteSpecificNode(22, '', ['table:display', 'style:writing-mode'],
        ['true', 'lr-tb']);
      ODSFile.WriteSpecificNode(1021, '', [], []);
      Exit;
    end;
    //Default Column Style
    if (TypeOfOptions = -1) then
    begin
      ODSFile.WriteSpecificNode(21, '', ['style:name', 'style:family'],
        ['DefaultColumnStyle', 'table-column']);
      ODSFile.WriteSpecificNode(23, '', [], []);
      ODSFile.WriteSpecificNode(1021, '', [], []);
      Exit;
    end;
    //Default Row Style
    if (TypeOfOptions = -2) then
    begin
      ODSFile.WriteSpecificNode(21, '', ['style:name', 'style:family'],
        ['DefaultRowStyle', 'table-row']);
      ODSFile.WriteSpecificNode(24, '', [], []);
      ODSFile.WriteSpecificNode(1021, '', [], []);
      Exit;
    end;
    //Default Cell style
    if (TypeOfOptions = 0) then
    begin
      ODSFile.WriteSpecificNode(21, '', ['style:name', 'style:family',
        'style:parent-style-name'], ['DefaultCell', 'table-cell', 'Default']);
      ODSFile.WriteSpecificNode(26, '', ['style:font-name', 'fo:font-size',
        'fo:color'], ['Arial', '10pt', '#000000']);
      ODSFile.WriteSpecificNode(29, '', ['fo:text-align'], ['start']);
      ODSFile.WriteSpecificNode(25, '', ['fo:background-color',
        'style:text-align-source', 'style:repeat-content', 'style:vertical-align'],
        ['#FFFFFF', 'fix', 'false', 'bottom']);
      ODSFile.WriteSpecificNode(1021, '', [], []);
      Exit;
    end;
    //Style for header
    if (TypeOfOptions = 1) then
    begin
      SubRoutine(ODSOptions.HeaderStyle, 'Header', ODSOptions.HeaderStyle.Border);
      Exit;
    end;
    //Style for footer
    if (TypeOfOptions = 2) then
    begin
      SubRoutine(ODSOptions.FooterStyle, 'Footer', ODSOptions.FooterStyle.Border);
      Exit;
    end;
    //Style for caption row
    if (TypeOfOptions = 3) then
    begin
      SubRoutine(ODSOptions.CaptionRowStyle, 'CaptionRow',
        ODSOptions.CaptionRowStyle.Border);
      Exit;
    end;
    //Style for DataStyle
    if (TypeOfOptions = 4) then
    begin
      SubRoutine(ODSOptions.DataStyle, 'DataStyle', ODSOptions.DataStyle.Border);
      Exit;
    end;

    //Style for StripStyles
    if (TypeOfOptions > 4) then
    begin
      SubRoutine(ODSOptions.StripStylesList[TypeOfOptions - 5],
        'StripStyle' + IntToStr(TypeOfOptions - 4),
          ODSOptions.StripStylesList[TypeOfOptions - 5].StripBorder);
      Exit;
    end;
  end;

  procedure WriteNumericFormats();
  begin
    ODSFile.WriteSpecificNode(31, '', [], []); // integer
    ODSFile.WriteSpecificNode(32, '', [], []); // float
    ODSFile.WriteSpecificNode(33, '', [], []); // date
    ODSFile.WriteSpecificNode(34, '', [], []); // time
    ODSFile.WriteSpecificNode(35, '', [], []); // datetime
    //ODSFile.WriteSpecificNode(36, '', [], []); // currency  // TODO
  end;

  procedure MakeStylesList();
  begin

  end;

//  function GetNumericFieldsCount: Integer;
//  begin
//    for I := 0 to List.Count - 1 do
//
//  end;

begin
  //+-------------------------------------+
  //|Default face-fonts processing section|
  //+-------------------------------------+
  ODSFile.OpenStream('facefont.xml');
  ODSFile.OpenWriter;
  for I := 1 to 4 do
  begin
    WriteFontStyleNode(I);
  end;
  for I := 0 to ODSOptions.StripStylesList.Count - 1 do
  begin
    WriteFontStyleNode(I + 5);
  end;
  ODSFile.WriteSpecificNode(1010, '', [], []);
  ODSFile.CloseWriter;
  ODSFile.CloseStream;
  ODSOptions.FontList.Clear;
  ODSFile.OpenStream('facefontstyles.xml');
  ODSFile.OpenWriter;
  for I := 1 to 4 do
    WriteFontStyleNode(I);
  for I := 0 to ODSOptions.StripStylesList.Count - 1 do
    WriteFontStyleNode(I + 5);
  ODSFile.WriteSpecificNode(1010, '', [], []);
  ODSFile.CloseWriter;
  ODSFile.CloseStream;
  //+-----------------------+
  //|Styles creation section|
  //+-----------------------+
  ODSFile.OpenStream('auto.xml');
  ODSFile.OpenWriter;
  ODSFile.WriteSpecificNode(11, '', [], []);
  for I := -3 to 4 do
    WriteCellStyleNode(I);
  for I := 0 to ODSOptions.StripStylesList.Count - 1 do
    WriteCellStyleNode(I + 5);
  ODSFile.WriteSpecificNode(1011, '', [], []);
  ODSFile.WriteSpecificNode(12, '', [], []);
  ODSFile.WriteSpecificNode(13, '', [], []);
  ODSFile.CloseWriter;
  ODSFile.CloseStream;
  ODSFile.OpenStream('autoStyles.xml');
  ODSFile.OpenWriter;
  ODSFile.WriteSpecificNode(27, '', [], []);
  for I := 0 to 4 do
    WriteCellStyleNode(I);
  for I := 0 to ODSOptions.StripStylesList.Count - 1 do
    WriteCellStyleNode(I + 5);
  ODSFile.WriteSpecificNode(1027, '', [], []);
  ODSFile.WriteSpecificNode(211, '', [], []);
  ODSFile.WriteSpecificNode(1028, '', [], []);
  ODSFile.CloseWriter;
  ODSFile.CloseStream;
end;

procedure TQExport4ODS.BeginExport;
var
  i: Integer;
  temp: WideString;
begin
  inherited;
  ODSFile.Renew;
  FRowCounter := 0;
  //ODS export
  ODSFile.TypeConvert := odfSpreadsheet;
  ODSFile.FileName := Self.FileName;
  ODSFile.MakeAll;

  Formats.ApplyParams;

  ODSFile.OpenStream('table.xml');
  ODSFile.OpenWriter;
  ODSFile.CheckStatus;
  ODSFile.WriteSpecificNode(15, '', ['table:name', 'table:style-name'],
    [SheetName, 'DefaultTableStyle']);
  for I := 0 to Columns.Count - 1 do
    ODSFile.WriteSpecificNode(19, '', ['table:style-name'], ['DefaultColumnStyle']);
  if (Header.Count > 0) then
  begin
    ODSFile.WriteSpecificNode(16, '', ['table:style-name'], ['DefaultRowStyle']);
    ODSFile.WriteSpecificNode(17, '', ['table:style-name', 'office:value-type'],
      ['Header', 'string']);
    for I := 0 to Header.Count - 1 do
    begin
      temp := Header[I];
      ODSFile.WriteSpecificNode(18, ReplaceSymbols(temp), [], []);
    end;
    ODSFile.WriteSpecificNode(1017, '', [], []);
    ODSFile.WriteSpecificNode(1016, '', [], []);
  end;
end;

function TQExport4ODS.ColorToString(Color: TColor): string;

  procedure SwapNums(Num1, Num2: Integer; var SwapStr: String);
  var
    a: char;
  begin
    a := SwapStr[Num1];
    SwapStr[Num1] := SwapStr[Num2];
    SwapStr[Num2] := a;
  end;

begin
  //Get Standard TColor representation
  FmtStr(Result, '%.6x', [Color]);
  //Swap 2 bytes to get defaul RGB representation
  SwapNums(1, 5, Result);
  SwapNums(2, 6, Result);
  Result := '#' + Result;
end;

constructor TQExport4ODS.Create(AOwner: TComponent);
begin
  inherited;
  ODSFile := TBaseODFFile.Create;
  FODSOptions := TQExportODSOptions.Create(Self);
  FTableName := QExportLoadStr(QED_ODS_StandardSheetName);
end;

destructor TQExport4ODS.Destroy;
begin
  ODSFile.Free;
  FODSOptions.Free;
  inherited;
end;

procedure TQExport4ODS.EndExport;
var
  I: integer;
  temp: WideString;
begin
  if (Footer.Count > 0) then
  begin
    ODSFile.WriteSpecificNode(16, '', ['table:style-name'], ['DefaultRowStyle']);
    ODSFile.WriteSpecificNode(17, '', ['table:style-name', 'office:value-type'],
      ['Footer', 'string']);
    for I := 0 to Footer.Count - 1 do
    begin
      temp := Footer[I];
      ODSFile.WriteSpecificNode(18, ReplaceSymbols(temp), [], []);
    end;
    ODSFile.WriteSpecificNode(1017, '', [], []);
    ODSFile.WriteSpecificNode(1016, '', [], []);
  end;
  ODSFile.WriteSpecificNode(1015, '', [], []);
  ODSFile.CloseWriter;
  ODSFile.CloseStream;
  ODSFile.EndFormingContent;
  AddStyles;
  ODSFile.MergeContent('content.xml', ['first.xml', 'facefont.xml', 'auto.xml',
    'table.xml', 'last.xml' ]);
  ODSFile.MergeContent('styles.xml', ['firstSt.xml', 'facefontstyles.xml',
    'autoStyles.xml']);
  ODSFile.DeleteList(['first.xml', 'facefont.xml', 'auto.xml',
    'table.xml', 'last.xml', 'firstSt.xml', 'facefontstyles.xml',
    'autoStyles.xml']);
  ODSFile.Compress;
  Formats.RestoreSeparators;
  inherited;
end;

procedure TQExport4ODS.Execute;
begin
  BeforeExecute;
  try
    if SheetName = '' then
      raise Exception.Create('Sheet name is not defined');
    DoExport;
    ShowResult;
  finally
    AfterExecute;
  end;
end;


function TQExport4ODS.PointsToCms(Value: Integer): string;
var
  TempString: string;
  Idx: Integer;
begin
  if Value = 0 then
  begin
    Result := '0cm';
    Exit;
  end;
  TempString := FloatToStr(Value * 0.0352);
  Idx := QEPos(',', TempString);
  TempString[Idx] := '.';
  Result := Copy(TempString, 1, 5);
  Result := Result + 'cm';
end;

procedure TQExport4ODS.SetOptions(const Value: TQExportODSOptions);
begin
  FODSOptions.Assign(Value);
end;

procedure TQExport4ODS.WriteCaptionRow;
var
  I: Integer;
  aaa: WideString;
begin
  ODSFile.WriteSpecificNode(16, '', ['table:style-name'], ['DefaultRowStyle']);
  for i := 0 to Columns.Count - 1 do
  begin
    ODSFile.WriteSpecificNode(17, '', ['table:style-name', 'office:value-type'],
      ['CaptionRow', 'string']);
    aaa := GetColCaption(i);
    ODSFile.WriteSpecificNode(18, ReplaceSymbols(aaa), [], []);
    ODSFile.WriteSpecificNode(1018, '', [], []);
    ODSFile.WriteSpecificNode(1017, '', [], []);
  end;
  ODSFile.WriteSpecificNode(1016, '', [], []);
end;

procedure TQExport4ODS.WriteDataRow;
var
  I, Num: Integer;
  CurrValue,
  CurrentData: WideString;
  ODFType: WideString;
begin
  Inc(FRowCounter);
  ODSFile.WriteSpecificNode(16, '', ['table:style-name'], ['DefaultRowStyle']);
  for I := 0 to ExportRow.Count - 1 do
  begin
    CurrValue := GetExportedValue(ExportRow[I]);
    CurrValue := ReplaceSymbols(CurrValue);
    ODFType := ExportTypeToODFType(Columns[I].ColType);
    if VarIsNull(ExportRow[I].Data) or VarIsEmpty(ExportRow[I].Data) then
    begin
      CurrentData := CurrValue;
      ODFType := odfStringTypeName;
    end
    else
    begin
      CurrentData := ExportRow[I].Data;

      if Columns[I].ColType in [ectFloat, ectCurrency, ectDateTime, ectNumeric] then
        CurrentData := CorrectExcelDecimalSepInValue(CurrentData);
      CurrentData := ReplaceSymbols(CurrentData);
    end;

    if (ODSOptions.StripStyle = sstNone) then
      ODSFile.WriteSpecificNode(17, '', ['office:value-type', 'office:value',
        'table:style-name'],
        [ODFType, CurrentData, 'DataStyle'])
    else
    begin
      //Column-style
      if (ODSOptions.StripStyle = sstColumn) then
      begin
        Num := (I + 1) mod ODSOptions.StripStylesList.Count;
        if (Num = 0) then
          Num := ODSOptions.StripStylesList.Count;
        ODSFile.WriteSpecificNode(17, '', ['office:value-type', 'office:value',
          'table:style-name'],
          [ODFType, CurrentData, 'StripStyle' + IntToStr(Num)]);
      end;
      //Row-style
      if (ODSOptions.StripStyle = sstRow) then
      begin
        Num := FRowCounter mod ODSOptions.StripStylesList.Count;
        if (Num = 0) then
          Num := ODSOptions.StripStylesList.Count;
        ODSFile.WriteSpecificNode(17, '', ['office:value-type', 'office:value',
          'table:style-name'],
          [ODFType, CurrentData,  'StripStyle' + IntToStr(Num)]);
      end;
    end;
    ODSFile.WriteSpecificNode(18, CurrValue, [], []);
    ODSFile.WriteSpecificNode(1017, '', [], []);
  end;
  ODSFile.WriteSpecificNode(1016, '', [], []);
end;

{ TQExportODSOptions }

procedure TQExportODSOptions.Assign(Source: TPersistent);
begin
  if Source is TQExportODSOptions then begin
    HeaderStyle := (Source as TQExportODSOptions).HeaderStyle;
    FooterStyle := (Source as TQExportODSOptions).FooterStyle;
    CaptionRowStyle := (Source as TQExportODSOptions).CaptionRowStyle;
    StripStylesList := (Source as TQExportODSOptions).StripStylesList;
    DataStyle := (Source as TQExportODSOptions).DataStyle;
    StripStyle := (Source as TQExportODSOptions).StripStyle;
    Exit;
  end;
  inherited;
end;

function TQExportODSOptions.CheckFontInList(FontName: string): Boolean;
var
  I: Integer;
begin
  Result := false;
  for I := 0 to FontList.Count - 1 do
    if (FontName = FontList[I]) then
    begin
      Result := true;
      Exit;
    end;
end;

constructor TQExportODSOptions.Create(Holder: TPersistent);
begin
  inherited Create;
  FHolder := Holder;
  FHeaderStyle := TODSCellParagraphStyle.Create(nil);
  FFooterStyle := TODSCellParagraphStyle.Create(nil);
  FCaptionRowStyle := TODSCellParagraphStyle.Create(nil);
  FDataStyle := TODSCellParagraphStyle.Create(nil);
  FStripStyle := sstNone;
  FStripStylesList := TODSStylesList.Create(Self);
  FFontList := TStringList.Create;
end;

destructor TQExportODSOptions.Destroy;
begin
  FHeaderStyle.Free;
  FFooterStyle.Free;
  FCaptionRowStyle.Free;
  FDataStyle.Free;
  FStripStylesList.Free;
  FFontList.Free;
  inherited;
end;

function TQExportODSOptions.GetOwner: TPersistent;
begin
  Result := FHolder;
end;

procedure TQExportODSOptions.SetCaptionStyle(const Value: TODSCellParagraphStyle);
begin
  FCaptionRowStyle.Assign(Value);
end;

procedure TQExportODSOptions.SetDataStyle(const Value: TODSCellParagraphStyle);
begin
  FDataStyle.Assign(Value);
end;

procedure TQExportODSOptions.SetFooterStyle(const Value: TODSCellParagraphStyle);
begin
  FFooterStyle.Assign(Value);
end;

procedure TQExportODSOptions.SetHeaderStyle(const Value: TODSCellParagraphStyle);
begin
  FHeaderStyle.Assign(Value);
end;


procedure TQExportODSOptions.SetStripStyles(const Value: TODSStylesList);
begin
  FStripStylesList.Assign(Value);
end;

end.
