diff --git a/components/fpspreadsheet/fpsopendocument.pas b/components/fpspreadsheet/fpsopendocument.pas index 94b842b62..4683403ca 100755 --- a/components/fpspreadsheet/fpsopendocument.pas +++ b/components/fpspreadsheet/fpsopendocument.pas @@ -2961,6 +2961,7 @@ var sheet: TsWorksheet; vsm, hsm, hsp, vsp: Integer; showGrid, showHeaders: Boolean; + actCol, actRow: Cardinal; i: Integer; begin showGrid := true; @@ -3027,14 +3028,14 @@ begin begin cfgName := GetAttrValue(node, 'config:name'); cfgValue := GetNodeValue(node); - if cfgName = 'VerticalSplitMode' then - vsm := StrToInt(cfgValue) - else if cfgName = 'HorizontalSplitMode' then - hsm := StrToInt(cfgValue) - else if cfgName = 'VerticalSplitPosition' then - vsp := StrToInt(cfgValue) - else if cfgName = 'HorizontalSplitPosition' then - hsp := StrToInt(cfgValue); + case cfgName of + 'CursorPositionX': actCol := StrToInt(cfgValue); + 'CursorPositionY': actRow := StrToInt(cfgValue); + 'VerticalSplitMode': vsm := StrToInt(cfgValue); + 'HorizontalSplitMode': hsm := StrToInt(cfgValue); + 'VerticalSplitPosition': vsp := StrToInt(cfgValue); + 'HorizontalSplitPosition': hsp := StrToInt(cfgValue); + end; end; node := node.NextSibling; end; @@ -3046,6 +3047,8 @@ begin end else sheet.Options := sheet.Options - [soHasFrozenPanes]; end; + // Active cell + sheet.SelectCell(actRow, actCol); end; end; cfgTableItemNode := cfgTableItemNode.NextSibling; @@ -5023,9 +5026,10 @@ procedure TsSpreadOpenDocWriter.WriteTableSettings(AStream: TStream); var i: Integer; sheet: TsWorkSheet; - hsm: Integer; // HorizontalSplitMode - vsm: Integer; // VerticalSplitMode - asr: Integer; // ActiveSplitRange + hsm: Integer; // HorizontalSplitMode + vsm: Integer; // VerticalSplitMode + asr: Integer; // ActiveSplitRange + actX, actY: Integer; // Active cell col/row index begin for i:=0 to Workbook.GetWorksheetCount-1 do begin @@ -5051,10 +5055,20 @@ begin end; {showGrid := (soShowGridLines in sheet.Options);} + if (sheet.ActiveCellRow <> cardinal(-1)) and (sheet.ActiveCellCol <> cardinal(-1)) then + begin + actX := sheet.ActiveCellCol; + actY := sheet.ActiveCellRow; + end else + begin + actX := sheet.LeftPaneWidth; + actY := sheet.TopPaneHeight; + end; + AppendToStream(AStream, - ''+IntToStr(sheet.LeftPaneWidth)+''); + ''+IntToStr(actX)+''); AppendToStream(AStream, - ''+IntToStr(sheet.TopPaneHeight)+''); + ''+IntToStr(actY)+''); AppendToStream(AStream, ''+IntToStr(hsm)+''); AppendToStream(AStream, diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 4308bc16b..d22834789 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -504,6 +504,7 @@ begin INT_EXCEL_ID_PRINTHEADERS: ReadPrintHeaders(AStream); INT_EXCEL_ID_RIGHTMARGIN : ReadMargin(AStream, 1); INT_EXCEL_ID_ROW : ReadRowInfo(AStream); + INT_EXCEL_ID_SELECTION : ReadSELECTION(AStream); INT_EXCEL_ID_STRING : ReadStringRecord(AStream); INT_EXCEL_ID_TOPMARGIN : ReadMargin(AStream, 2); INT_EXCEL_ID_DEFROWHEIGHT: ReadDefRowHeight(AStream); diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 853980582..e6be37d0f 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -431,6 +431,7 @@ begin INT_EXCEL_ID_RK : ReadRKValue(AStream); //(RK) This record represents a cell that contains an RK value (encoded integer or floating-point value). If a floating-point value cannot be encoded to an RK value, a NUMBER record will be written. This record replaces the record INTEGER written in BIFF2. INT_EXCEL_ID_ROW : ReadRowInfo(AStream); INT_EXCEL_ID_RSTRING : ReadRString(AStream); //(RSTRING) This record stores a formatted text cell (Rich-Text). In BIFF8 it is usually replaced by the LABELSST record. Excel still uses this record, if it copies formatted text cells to the clipboard. + INT_EXCEL_ID_SELECTION : ReadSELECTION(AStream); INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream); INT_EXCEL_ID_SHEETPR : ReadSHEETPR(AStream); INT_EXCEL_ID_STANDARDWIDTH : ReadStandardWidth(AStream, FWorksheet); diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index b8f794a3c..62ec4775e 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -819,6 +819,7 @@ begin // This record replaces the record INTEGER written in BIFF2. INT_EXCEL_ID_RK : ReadRKValue(AStream); + INT_EXCEL_ID_SELECTION : ReadSELECTION(AStream); INT_EXCEL_ID_SHAREDFMLA : ReadSharedFormula(AStream); INT_EXCEL_ID_SHEETPR : ReadSHEETPR(AStream); INT_EXCEL_ID_STRING : ReadStringRecord(AStream); diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 45a2bfd55..5a6778b85 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -431,6 +431,7 @@ type function ReadRPNTokenArray(AStream: TStream; ACell: PCell; ASharedFormulaBase: PCell = nil): Boolean; function ReadRPNTokenArraySize(AStream: TStream): word; virtual; + procedure ReadSELECTION(AStream: TStream); procedure ReadSharedFormula(AStream: TStream); procedure ReadSHEETPR(AStream: TStream); @@ -543,7 +544,7 @@ type procedure WriteRPNTokenArraySize(AStream: TStream; ASize: Word); virtual; // Writes out a SELECTION record - procedure WriteSelection(AStream: TStream; ASheet: TsWorksheet; APane: Byte); + procedure WriteSELECTION(AStream: TStream; ASheet: TsWorksheet; APane: Byte); procedure WriteSelections(AStream: TStream; ASheet: TsWorksheet); (* // Writes out a shared formula @@ -2163,6 +2164,35 @@ begin Result := WordLEToN(AStream.ReadWord); end; +{@@ ---------------------------------------------------------------------------- + Reads a SELECTION record containing the currently selected cell + Valid for BIFF2-BIFF8. +-------------------------------------------------------------------------------} +procedure TsSpreadBIFFReader.ReadSELECTION(AStream: TStream); +var + actPane: byte; + actRow, actCol: Word; + rngIndex: Word; + i, numRanges: Word; +begin + // Active pane + actPane := AStream.ReadByte; + + // Row index of the active cell + actRow := WordLEToN(AStream.ReadWord); + + // Column index of the active cell + actCol := WordLEToN(AStream.ReadWord); + + // Index into the following range list which contains the active cell + rngIndex := WordLEToN(AStream.ReadWord); + + // Count of selected ranges + // Selected ranges --> ignore + + FWorksheet.SelectCell(actRow, actCol); +end; + {@@ ---------------------------------------------------------------------------- Reads a SHAREDFMLA record, i.e. reads cell range coordinates and a rpn formula. The formula is applied to all cells in the range. The formula is @@ -3695,29 +3725,34 @@ end; APane is 0..3 (see below) Valid for BIFF2-BIFF8 -------------------------------------------------------------------------------} -procedure TsSpreadBIFFWriter.WriteSelection(AStream: TStream; +procedure TsSpreadBIFFWriter.WriteSELECTION(AStream: TStream; ASheet: TsWorksheet; APane: Byte); var activeCellRow, activeCellCol: Word; begin - case APane of - 0: begin // right-bottom - activeCellRow := ASheet.TopPaneHeight; - activeCellCol := ASheet.LeftPaneWidth; - end; - 1: begin // right-top - activeCellRow := 0; - activeCellCol := ASheet.LeftPaneWidth; - end; - 2: begin // left-bottom - activeCellRow := ASheet.TopPaneHeight; - activeCellCol := 0; - end; - 3: begin // left-top - activeCellRow := 0; - activeCellCol := 0; - end; - end; + if FWorkbook.ActiveWorksheet <> nil then + begin + activeCellRow := FWorksheet.ActiveCellRow; + activeCellCol := FWorksheet.ActiveCellCol; + end else + case APane of + 0: begin // right-bottom + activeCellRow := ASheet.TopPaneHeight; + activeCellCol := ASheet.LeftPaneWidth; + end; + 1: begin // right-top + activeCellRow := 0; + activeCellCol := ASheet.LeftPaneWidth; + end; + 2: begin // left-bottom + activeCellRow := ASheet.TopPaneHeight; + activeCellCol := 0; + end; + 3: begin // left-top + activeCellRow := 0; + activeCellCol := 0; + end; + end; { BIFF record header } WriteBIFFHeader(AStream, INT_EXCEL_ID_SELECTION, 15); @@ -3963,6 +3998,8 @@ end; Valid for BIFF5-BIFF8. -------------------------------------------------------------------------------} procedure TsSpreadBIFFWriter.WriteWindow1(AStream: TStream); +var + actSheet: Integer; begin { BIFF Record header } WriteBIFFHeader(AStream, INT_EXCEL_ID_WINDOW1, 18); @@ -3986,7 +4023,10 @@ begin MASK_WINDOW1_OPTION_WORKSHEET_TAB_VISIBLE)); { Index to active (displayed) worksheet } - AStream.WriteWord(WordToLE($00)); + if FWorkbook.ActiveWorksheet = nil then + actSheet := 0 else + actSheet := FWorkbook.GetWorksheetIndex(FWorkbook.ActiveWorksheet); + AStream.WriteWord(WordToLE(actSheet)); { Index of first visible tab in the worksheet tab bar } AStream.WriteWord(WordToLE($00)); diff --git a/components/fpspreadsheet/xlsxooxml.pas b/components/fpspreadsheet/xlsxooxml.pas index 2cec876af..63e60836e 100755 --- a/components/fpspreadsheet/xlsxooxml.pas +++ b/components/fpspreadsheet/xlsxooxml.pas @@ -1751,6 +1751,7 @@ var childNode: TDOMNode; nodeName: String; s: String; + actRow, actCol: Cardinal; begin if ANode = nil then exit; @@ -1778,6 +1779,14 @@ begin s := GetAttrValue(childNode, 'ySplit'); if s <> '' then AWorksheet.TopPaneHeight := StrToInt(s); end; + end else + if nodeName = 'selection' then begin + s := GetAttrValue(childnode, 'activeCell'); + if s <> '' then + begin + ParseCellString(s, actRow, actCol); + AWorksheet.SelectCell(actRow, actCol); + end; end; childNode := childNode.NextSibling; end; @@ -3025,6 +3034,8 @@ var topRightCell: String; bottomLeftCell: String; bottomRightCell: String; + actCell: String; + tabSel: String; begin // Show gridlines ? showGridLines := StrUtils.IfThen(soShowGridLines in AWorksheet.Options, ' ', 'showGridLines="0" '); @@ -3032,63 +3043,86 @@ begin // Show headers? showHeaders := StrUtils.IfThen(soShowHeaders in AWorksheet.Options, ' ', 'showRowColHeaders="0" '); + // Active cell + if (AWorksheet.ActiveCellRow <> cardinal(-1)) and (AWorksheet.ActiveCellCol <> cardinal(-1)) then + actCell := GetCellString(AWorksheet.ActiveCellRow, AWorksheet.ActiveCellCol) else + actCell := ''; + + // Selected tab? + tabSel := StrUtils.IfThen(AWorksheet = FWorkbook.ActiveWorksheet, 'tabSelected="1" ', ''); + // No frozen panes if not (soHasFrozenPanes in AWorksheet.Options) or ((AWorksheet.LeftPaneWidth = 0) and (AWorksheet.TopPaneHeight = 0)) then + begin + if actCell = '' then actCell := 'A1'; AppendToStream(AStream, Format( '' + - '' + + '' + + '' + + '' + '', [ - showGridLines, showHeaders + showGridLines, showHeaders, tabSel, + actCell, actCell ])) - else + end else begin // Frozen panes topRightCell := GetCellString(0, AWorksheet.LeftPaneWidth, [rfRelRow, rfRelCol]); bottomLeftCell := GetCellString(AWorksheet.TopPaneHeight, 0, [rfRelRow, rfRelCol]); bottomRightCell := GetCellString(AWorksheet.TopPaneHeight, AWorksheet.LeftPaneWidth, [rfRelRow, rfRelCol]); if (AWorksheet.LeftPaneWidth > 0) and (AWorksheet.TopPaneHeight > 0) then + begin + if actCell = '' then + actCell := bottomRightcell; AppendToStream(AStream, Format( '' + - ''+ + ''+ '' + '' + '' + '' + '' + '', [ - showGridLines, showHeaders, + showGridLines, showHeaders, tabSel, AWorksheet.LeftPaneWidth, AWorksheet.TopPaneHeight, bottomRightCell, topRightCell, topRightCell, bottomLeftCell, bottomLeftCell, - bottomRightCell, bottomrightCell + actCell, actCell ])) - else + end else if (AWorksheet.LeftPaneWidth > 0) then + begin + if actCell = '' then + actCell := topRightCell; AppendToStream(AStream, Format( '' + - ''+ + ''+ '' + '' + '' + '', [ - showGridLines, showHeaders, + showGridLines, showHeaders, tabSel, AWorksheet.LeftPaneWidth, topRightCell, - topRightCell, topRightCell + actCell, actCell ])) - else + end else if (AWorksheet.TopPaneHeight > 0) then + begin + if actCell = '' then + actCell := bottomLeftCell; AppendToStream(AStream, Format( ''+ - ''+ + ''+ ''+ '' + ''+ '', [ - showGridLines, showHeaders, + showGridLines, showHeaders, tabSel, AWorksheet.TopPaneHeight, bottomLeftCell, - bottomLeftCell, bottomLeftCell + actCell, actCell ])); + end; end; end;