Top > OOobbs3 > 43

OOobbs3/43 Edit

  • サマリ: オート Sum っぽいマクロ
  • 環境: Calc
  • 状態: 投稿
  • 投稿者: はにゃ??
  • 投稿日: 2011-01-05 (水) 21:41:33

質問 Edit

オート Sum に対応するコマンドが見つからないので issue を漁ると http://www.openoffice.org/issues/show_bug.cgi?id=45563

それらしくマクロで書いてみた。

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
Sub AutoSumForCalc
  oDoc = ThisComponent
  If NOT oDoc.supportsService("com.sun.star.sheet.SpreadsheetDocument") Then Exit Sub
  
  nCellFlags = com.sun.star.sheet.CellFlags
  nCellType = com.sun.star.table.CellContentType
  
  oSelection = oDoc.getCurrentSelection()
  
  If oSelection.supportsService("com.sun.star.sheet.SheetCell") Then
    ' single cell mode
    oCell = oSelection
    oSheet = oCell.getSpreadsheet()
    aCellAddr = oCell.getCellAddress()
    
    oCellRange = oSheet.getCellRangeByPosition( _
        aCellAddr.Column, 0, aCellAddr.Column, aCellAddr.Row - 1)
    
    oRanges = oCellRange.queryContentCells(nCellFlags.VALUE + nCellFlags.FORMULA + nCellFlags.STRING)
    If oRanges.getCount() Then
      oRange = oRanges.getByIndex(oRanges.getCount() - 1)
      aRangeAddr = oRange.getRangeAddress()
      If aRangeAddr.EndRow < aCellAddr.Row - 1 Then
        oRange = oSheet.getCellRangeByPosition( _
            aRangeAddr.StartColumn, aRangeAddr.StartRow, _
            aRangeAddr.EndColumn, aCellAddr.Row - 1)
      End If
      
      sFormula = "=SUM(" & GetRangeAddress(oRange) & ")"
      
      oCell.setFormula(sFormula)
      ToEditMode(oDoc)
    End If
    
  ElseIf oSelection.supportsService("com.sun.star.sheet.SheetCellRange") Then
    oCellRange = oSelection
    aRangeAddr = oCellRange.getRangeAddress()
    
    ' check all last rows are empty
    bAllEmpty = True
    nRow = aRangeAddr.EndRow - aRangeAddr.StartRow
    For i = 0 To (aRangeAddr.EndColumn - aRangeAddr.StartColumn) step 1
      oCell = oCellRange.getCellByPosition(i, nRow)
      If oCell.getType() <> nCellType.EMPTY Then
        bAllEmpty = False
      End If
    Next
    If bAllEmpty Then
      ' set sum in each cell of the last row
      If (aRangeAddr.EndRow - aRangeAddr.StartRow) > 0 Then
        For i = 0 To (aRangeAddr.EndColumn - aRangeAddr.StartColumn) step 1
          oCell = oCellRange.getCellByPosition(i, nRow)
          oCellRange2 = oCellRange.getCellRangeByPosition(i, 0, i, nRow - 1)
          sFormula = "=SUM(" & GetRangeAddress(oCellRange2) & ")"
          oCell.setFormula(sFormula)
        Next
      End If
    Else
      oSheet = oCellRange.getSpreadsheet()
      
      On Error GoTo IndexOutOfBoundExceptionHandle
      For i =aRangeAddr.StartColumn To aRangeAddr.EndColumn step 1
        oCell = oSheet.getCellByPosition(i, nRow)
        oRange = oSheet.getCellRangeByPosition(i, aRangeAddr.StartRow, i, aRangeAddr.EndRow)
        
        sFormula = "=SUM(" & GetRangeAddress(oRange) & ")"
        oCell.setFormula(sFormula)
      Next
      IndexOutOfBoundExceptionHandle:
    End If
  End If
End Sub
 
 
Function GetRangeAddress(oRange As Object) As String
  sAddress = ""
  If oRange.supportsService("com.sun.star.sheet.SheetCellRange") Then
    aRangeAddr = oRange.getRangeAddress()
    sAddress = ConvertToColumn(aRangeAddr.StartColumn) & CStr(aRangeAddr.StartRow + 1) & ":" & _
        ConvertToColumn(aRangeAddr.EndColumn) & CStr(aRangeAddr.EndRow + 1)
  End If
  GetRangeAddress = sAddress
End Function
 
 
Function ConvertToColumn(nColumn As Long) As String
  nCol = nColumn
  nMod = nCol mod 26
  sAddr = chr(65 + nMod)
  nCol = (nCol - nMod) / 26
  While nCol > 26
    nMod = nCol mod 26
    sAddr = chr(65 + nMod - 1) & sAddr
    nCol = (nCol - nMod) / 26
  WEnd
  If nCol >= 1 Then sAddr = chr(65 + nCol - 1) & sAddr
  
  ConvertToColumn = sAddr
End Function
 
 
Sub ToEditMode(oDoc)
  dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")
  dispatcher.executeDispatch(oDoc.getCurrentController(), _
      ".uno:SetInputMode", "", 0, Array())
End Sub

実行後の選択状態などを同じにしようとしたが方法がない。

Dim n As Long, m As Long, p As Long
n = 25
m = 26
p = n / m

このとき p = 1 になる…せいで手間取ったり…。

拡張機能パッケージを作成しました。

fileAutoSumForCalc-0.0.1.oxt

使い方

  1. 拡張機能パッケージを拡張機能マネージャからインストールします。
  2. Calc のドキュメントを作成します。
  3. ツール - カスタマイズ - キーボードを選択します。
  4. ショートカットキーに割り当てたいキーを選択します。
  5. 左下の範囲から、OpenOffice.org マクロ - user - mytools_AutoSumForCalc - Module1 を選択。
  6. 中央の機能で AutoSumForCalc を選択。
  7. 右上にある変更ボタンをクリック。
  8. OK ボタンをクリックしてダイアログを閉じます。

仕様について

  • マクロライブラリ名: mytools_AutoSumForCalc
  • マクロ名: mytools_AutoSumForCalc.Module1.AutoSumForCalc

実行後の挙動が既存のオート Sum とは異なります。

  • 戻る機能を利用したときに一段階で元にもどらないことがあります。
  • 単一セルを選択状態で実行したとき、実行後にセルが編集状態になっていても範囲アドレスの部分が選択されていない。
    • アクセシビリティ API を利用すれば・・・。
  • 複数の列が選択されている状態のとき、実行後に範囲のセルが選択されません。
    • これは、範囲を選択させるとセルカーソルが範囲の左上に移動して表示範囲が大きく変更されてしまうのを防ぐために実装していません。
  • Alt + = キーにショートカットが割当てていない。
    • Alt + = キーは OOo ではショートカットキーとして利用できません。

ショートカットキー用のコンフィグファイルを作成しましたが、どのキーに割り当てましょうかねぇ…。

ToDo

  • 列方向に sum 対象が見つからないときに行方向を探す

回答 Edit


感想,コメント,メモ Edit



Attach file: fileAutoSumForCalc-0.0.1.oxt 999 download [Information]

Reload   New Lower page making Edit Freeze Diff Upload Copy Rename   Front page List of pages Search Recent changes Backup   Help   RSS of recent changes