午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

図形のテキストボックスの段落のタブの配置をVBAで正確に取得できないことがあったので調べてみた

 
 
図形やテキストボックスの中の文字列をセルにコピーするマクロ
'選択状態の図形の文字列を近くのセルへコピー
'複数行なら複数セルを使用
Sub ShapeTextToCell()
    Dim i As Integer
    Dim str As String
    
    Dim s As Shape
    Set s = Selection.ShapeRange.Item(1) '選択図形取得
    Dim pRange As Range '貼り付け先のセル
    Set pRange = s.topLeftCell  '図形の左上にあるセル
    Dim tr As TextRange2
    Set tr = s.TextFrame2.TextRange '図形のテキスト全体(textRange)を取得
    '1行ごとにセルに文字を入力
    For i = 1 To tr.Paragraphs.Count
        str = tr.Paragraphs.Item(i).text '図形から文字列取得
        str = Replace(str, vbLf, "") '改行を削除
'        str = Replace(str, vbNewLine, "") 'これだと改行が削除されない
        pRange.Cells(i, 1).Value = str 'セルに入力
    Next
End Sub
 
 
イメージ 1
文字のある図形を選択した状態でマクロを実行すると
 
イメージ 2
図形の中の文字列が図形の左上のセルにコピーされる
 
イメージ 3
文字列に改行がある複数行の場合はコピー先も複数行になる
 
 
 
やっぱり可逆だよね
複数行のセルの値をまとめて1つのテキストボックスにするマクロ ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14674215.html今回のマクロはここから始まったセルの値をテキストボックスにするマクロの逆
一方通行より双方向
 
目的は
午後ツールその55、選択セル範囲を図形のテキストボックスにする、印刷用の点線を消すマクロを追加 ( Windows ) - 午後わてんのブログ - Yahoo!ブログ
http://blogs.yahoo.co.jp/gogowaten/14715274.html
このアドインで作成したテキストボックスの文字列をセルに戻せるようにすること
 
 
 
 
蛇足だけど複数列から作った文字列の場合
'選択状態の図形の文字列を近くのセルへコピー
'複数行複数列、TableTextBoxtestで作成したテキストボックス用
Sub ShapeTextToCell5()
    Dim i As Long, j As Long
    Dim str As String
    
    Dim s As Shape
    Set s = Selection.ShapeRange.Item(1)
    Dim pRange As Range '貼り付け先
    Set pRange = s.topLeftCell  '図形の左上にあるセル
    
    Dim tr As TextRange2
    Set tr = s.TextFrame2.TextRange '図形のテキスト全体(textRange)を取得
    Dim ptr As TextRange2
    Dim ptrFont As Font2
    Dim tRange As Range
    Dim v() As String
    '行ごと
    For i = 1 To tr.Paragraphs.Count
        Set ptr = tr.Paragraphs.Item(i)
        str = ptr.text
        str = Replace(str, vbLf, "") '改行削除
        '先頭のタブ文字削除
        If Left(str, 1) = vbTab Then
            str = Right(str, Len(str) - 1)
        End If
        v = Split(str, vbTab) 'タブ文字で区切って配列に入れる
        '1セルごと、1行の左から右へ1セルごと
        For j = 0 To UBound(v)
            Set tRange = pRange.Cells(i, j + 1)
            tRange.Value = v(j)
        Next
    Next
End Sub
 
イメージ 4
テキストボックスの文字列にはタブ文字(vbTab)を入れて元のセル間隔を再現しているので、Split関数でタブ文字で区切ればセルごとの文字列になる
        v = Split(str, vbTab) 'タブ文字で区切って配列に入れる
あとは先頭にあるタブ文字は要らないので削除、これでOK
 
 
 
 
ここからが本当の地獄だヽ(・ω・)/
 
図形のテキストボックスの段落のタブの配置をVBAで正確に取得できないことがあったので調べてみた
イメージ 5
日付って入れたセルだけ中央揃えにしたものから作ったテキストボックス、1行目(段落)を見ると
 
イメージ 6
1個めのタブの配置は中央、2個めのタブの配置は左に設定されている
セルにコピーするときに反映するにはこの配置の値を取得する必要がある
この値は図形の1行目の1個めの場合は
図形.TextFrame2.TextRange.Paragraphs.Item(1).ParagraphFormat.TabStops.Item(1).Type
これで取得できる
けど状況によっては正しく取得できなくなることがある
僕の書き方が良くないのかもしれないけど、よくわからん
対処法としての結論が
正しい値を取得するには上のように図形から直接するか
変数に入れるときは
図形.TextFrame2、
図形.TextFrame2.TextRange
ここまでにする、例えば図形.TextFrame2.TextRangeから
    Dim tr As TextRange2
    Set tr = 図形.TextFrame2.TextRange
    Set ts01 = tr.Paragraphs.Item(1).ParagraphFormat.TabStops.Item(1)
    Set ts02 = tr.Paragraphs.Item(1).ParagraphFormat.TabStops.Item(2)
    type01 = tr.Paragraphs.Item(1).ParagraphFormat.TabStops.Item(1).Type
    type02 = tr.Paragraphs.Item(1).ParagraphFormat.TabStops.Item(2).Type
これならOK
 
 
 
正しい値が取得できないのはもっと深いところを変数に入れてそこから取得する時
図形.TextFrame2.TextRange.Paragraphs.Item(1)
図形.TextFrame2.TextRange.Paragraphs.Item(1).ParagraphFormat
図形.TextFrame2.TextRange.Paragraphs.Item(1).ParagraphFormat.TabStops
これを変数に入れてそこから取得するとおかしくなる
 
 
 
ここから経緯
 
Sub testtabs5()
    Dim s As Shape
    Set s = Selection.ShapeRange.Item(1)
    Dim ts01 As TabStop2, ts02 As TabStop2
    Dim type01 As MsoTabStopType, type02 As MsoTabStopType
    
    Dim pf As ParagraphFormat2
    Set pf = s.TextFrame2.TextRange.Paragraphs.Item(1).ParagraphFormat
    Set ts01 = pf.TabStops.Item(1)
    Set ts02 = pf.TabStops.Item(2)
    type01 = pf.TabStops.Item(1).Type
    type02 = pf.TabStops.Item(2).Type        
End Sub
イメージ 7
 
イメージ 8
このマクロは選択図形の文字列の1行目の1個めと2個めのタブとその配置を取得するもの
配置はそれぞれtype01とtype02に取得する
期待する結果は
type01 = msoTabStopCenter '中央
type02 = msoTabStopLeft '左
なんだけど…
イメージ 9
type01 = msoTabStopCenter '中央
type02 = msoTabStopCenter '中央
と、2個めの配置が正しく取得できていない、なんで?
 
イメージ 12
取得したタブの中を見ても正しい値にはなっていない
 
 
 
次にタブの取得をする9,10行目をコメントアウトして
イメージ 10
これを実行
 
イメージ 11
type01 = msoTabStopCenter '中央
type02 = msoTabStopLeft '左
正確に取得できる
タブを取得した時点でおかしくなるみたい…
⊂( ・∀・)ワケ ( ・∀・)つワカ ⊂( ・∀・)つラン♪


それでも一番上から直接取得するようにして
図形.TextFrame2.TextRange.Paragraphs.Item(1).ParagraphFormat.TabStops.Item(2).Type
ってすると
イメージ 13
正確に取得できるので
ParagraphFormatを変数に入れて
その変数からタブを取得するとおかしくなる?


ParagraphFormatの上のParagraphから取得してみる
イメージ 14
これでも間違っている
 
 
もう1個上のTextRangeから取得してみる
イメージ 15
正確に取得できた!
 
 
これでなんとかなるかなあ
イメージ 16
もっと簡単にできるかと思っていたけど思わぬ落とし穴?があった
次は文字の装飾