VBAで(オートシェイプ(図形)を含めた)シート上の全ての文言を取得する
VBAでワークシート上にある全ての文言を取得する方法について書きます。
1.オートシェイプ(図形)の文言を取得する
セル内の文言はRange("A1").Valueなどで簡単に取得できますが、
以下の様なオートシェイプ(図形)に含まれる文言は
ShapesオブジェクトのTextFrameプロパティから取得する必要があります。
[サンプル]
以下のサンプルでは、アクティブシート上にある1番目の図形から、レイアウト枠内のテキスト表示します。
MsgBox ActiveSheet.Shapes(1).TextFrame.Characters.text |
Shapes()の引数は図形の名称でも構いません。
直線など、図形にレイアウト枠がない場合、エラーとなります。
2.シート上にある全てのオートシェイプ(図形)から文言を取得する
以上の内容をもとに、シート上にある全てのオートシェイプから文言を取得するFunctionを作成しました。
[ソース]
Public Function getShapesProperty(bookName As String, sheetName As String) As String() '------------------------------------------ 'getShapesText '対象シート上にあるオブジェクトのプロパティを取得する '引数1:bookName as String 対象ブック名 '引数2:sheetName as String 対象シート名 '戻り:getShapesProperty as string(2,n) ' (0,n) .type ' (1,n) .name ' (2,n) .TextFrame.Characters.text ' (3,n) .Left ' (4,n) .Top ' (5,n) .Width ' (6,n) .Height ' (7,n) .TopLeftCell.Address(False, False) ' (8,n) .BottomRightCell.Address(False, False) ' '------------------------------------------ Dim ret() As String Dim i As Long Dim obj As Object For Each obj In Workbooks(bookName).Sheets(sheetName).Shapes ReDim Preserve ret(8, i) As String ret(0, i) = CStr(obj.Type) ret(1, i) = CStr(obj.Name) 'TextFrameプロパティが使用できない(レイアウト枠がない)オブジェクトは除外 On Error Resume Next ret(2, i) = obj.TextFrame.Characters.text ret(3, i) = CStr(obj.Left) ret(4, i) = CStr(obj.Top) ret(5, i) = CStr(obj.Width) ret(6, i) = CStr(obj.Height) ret(7, i) = CStr(obj.TopLeftCell.Address(False, False)) ret(8, i) = CStr(obj.BottomRightCell.Address(False, False)) i = i + 1 Next getShapesProperty = ret End Function |
文言のほか、図形の幅などの情報も持たせたString配列を返却します。
レイアウト枠がない図形は、エラーをスキップして処理しています(On Error Resume Next)。
(もう少しきれいな方法があれば良かったんですが。。。)
2.1.テストしてみる(オートシェイプの文言取得)
以下のソースを実行して、テストしてみます。[テストコード]
Sub test_getShepesProperty() Dim str() As String str = getShapesProperty(ThisWorkbook.name, ActiveSheet.name) Dim msg As String Call addMsg(msg, "オートシェイプのプロパティを取得") Dim i As Long For i = 0 To UBound(str, 2) Call addMsg(msg, "図形:" + CStr(i + 1)) Call addMsg(msg, "図形種別(.Type):" + str(0, i)) Call addMsg(msg, "名称(.Name):" + str(1, i)) Call addMsg(msg, "文言(.TextFrame.Characters.text):" + str(2, i)) Call addMsg(msg, "左位置(.Left):" + str(3, i)) Call addMsg(msg, "上位置(.Top):" + str(4, i)) Call addMsg(msg, "幅(.Width):" + str(5, i)) Call addMsg(msg, "高さ(.Height):" + str(6, i)) Call addMsg(msg, "図形左上のセル(.TopLeftCell.Address):" + str(7, i)) Call addMsg(msg, "図形右下のセル(.BottomRightCell.Address):" + str(8, i)) Call addMsg(msg) Next i MsgBox msg End Sub Sub addMsg(msg As String, Optional addMsg = "") msg = msg + addMsg + vbCrLf End Sub |
以下はテスト用のシートです。
全てのオートシェイプから、文言を取得することができました。
3.シート上の全てのセル内の文言を取得する
一応、セル内の文言を取得するFunctionも作成しました。
[ソース]
Function getTextOnCell(bookName As String, sheetName As String) As String() '------------------------------------------ 'getTextOnCell '対象シート上にあるセル内の文言を取得する ' '戻り:getTextOnCell as string(2,n) ' (0,n) 行 ' (1,n) 列 ' (2,n) 文言 ' '------------------------------------------ Workbooks(bookName).Sheets(sheetName).Activate Dim ret() As String Dim r As Long 'ret()用カウンタ Dim sRow As Long Dim sCol As Long Dim lRow As Long Dim lCol As Long sRow = 1 sCol = 1 Call getRange(sheetName, lRow, lCol) 'データ Dim i As Long Dim j As Long Dim str As String For i = sRow To lRow For j = sCol To lCol str = Workbooks(bookName).Sheets(sheetName).Cells(i, j).Value If str <> "" Then ReDim Preserve ret(2, r) As String ret(0, r) = CStr(i) ret(1, r) = CStr(j) ret(2, r) = str r = r + 1 Else '処理なし End If Next j Next i getTextOnCell = ret End Function Sub getRange(sheetName As String, lRow As Long, lCol As Long) '------------------------------------------------------------------------------------ 'getRange 'シート最終行列の設定 '引数1:sheetName・・・・・・シート名 '引数2:lRow ・・・・・・・・最終行 '引数3:lCol ・・・・・・・・最終列 ' '------------------------------------------------------------------------------------ s = Sheets(sheetName).UsedRange.Address '有効レンジ範囲 lRow = Range(s).Rows(Range(s).Rows.count).Row '最終行 lCol = Range(s).Columns(Range(s).Columns.count).Column '最終列 End Sub |
引数にはブック名、シート名を指定します。
セル(1, 1)から最終セルまでの文言を取得し、String配列で返却します。
3.2.テストしてみる(セル内の文言取得)
以下のテストコードを実行し、テストしてみます。
Sub test_getTextOnCell() Dim str() As String str = getTextOnCell(ThisWorkbook.name, ActiveSheet.name) Dim msg As String Call addMsg(msg, "セル内の文言一覧") Call addMsg(msg) Dim i As Long For i = 0 To UBound(str, 2) Call addMsg(msg, "行:" + str(0, i)) Call addMsg(msg, "列:" + str(1, i)) Call addMsg(msg, "文言:" + str(2, i)) Call addMsg(msg) Next i MsgBox msg End Sub Sub addMsg(msg As String, Optional addMsg = "") msg = msg + addMsg + vbCrLf End Sub |
以下はテスト用シートです。
以上の通り、セル内の文言を取得できました。
今回作成した2つのFunctionで、シート上の全ての文言を取得できます。