シーゴの Excel 研究室

タイトル変更しました (旧称:今日を乗り切るExcel研究所)

Excel カギ線コネクタのちょいズレをまっすぐにしたい

今回は図形を繋ぐカギ線コネクタが微妙にズレるのをまっすぐにする方法を調べました。 またコネクタのズレを真っ直ぐにするマクロを作成します。

f:id:shego:20190106000504p:plain

カギ線コネクタのちょいズレ問題

Excel でもちょっとした図を描きたいことがままあります。

「図形」に用意されているオートシェープやコネクタを使えば、フローチャートなど手軽に描けると思うのですが、 これがまたクセがあってなかなか思い通りになりません。

中でも、「カギ線コネクタ」が、真っ直ぐになるはずのところで微妙にズレてしまうという問題には、本当に困ったものです。

「配置」>「左右の中央揃え」コマンドなどで中央揃え済みのハコの並びを、カギ線コネクタで繋いでいった時に、中心線となるべき線がなぜか直線にならず、微妙な段差の入った、しかも半分ぼやけた線になるのです。

f:id:shego:20190117021608p:plain

図形の座りのせいかと、ハコのほうの位置や大きさをちょっとずつずらしてみたりしますが、行ったり来たりするだけで、どうしても真っ直ぐになってくれません。

これをコネクタの「ちょいズレ」問題とでも呼んでおきましょうか。

みなさんはこの「ちょいズレ」があっても、許容できますか。

筆者的には、到底、許し難いことです。

ちょいズレコネクタを真っ直ぐにするには

いろいろ実験してみました。

まず、ちょいズレは必ず起こるというわけではないようです。 接続した両端の図形の種類や大きさのに違いがあると、真っ直ぐになることもあります。 なにか条件があるのかもしれませんが、よく分かりません。

条件があったとしても、コピー&ペーストした全く同じ形とサイズのオートシェイプの間では必ずちょいズレを起こすので、意味がありません。

線の種類にもよります。

コネクタの線形には「カギ線」、「直線」、「曲線」の3種類がありますが、ちょいズレ問題が起きるのは「カギ線」と「曲線」の場合のことで、「直線」コネクタなら正しく水平線・垂直線になります。

f:id:shego:20190106004434p:plain

さらに、ちょいズレになっているコネクタの「サイズ」を確認してみると、「高さ」が「0.04cm」という微妙な値になっています。

f:id:shego:20190106011344p:plain

試しに高さに 0 を入力すると、なんと真っ直ぐになります。 つまり、この微妙な高さの分が、ちょいズレの段差となって現れているのです。

この「0.04cm」という中途半端な数字はどこからくるのでしょうか。 フォントの単位でいう1ポイント分のズレだという説がありますが、計算してみるとたしかにそれに近い値になります。

ちょいズレは計算誤差でしょうか、バグでしょうか、それとも仕様なのでしょうか。

いずれにしろ、ちょいズレを直すには以下の2つの対処法が考えられます。

カギ線コネクタの高さを0にするには

要はちょいズレコネクタの不要な高さを 0 cm に直してあげればいいだけです。

コネクタ高さを設定するには、

  1. 対象 コネクタを選択します
  2. 「描画ツール/書式」タブの右端にある「サイズ」で上の入力欄(図形の高さ)に0を入力します。
    • キー操作:Alt + JD -> H -> 0 -> Enter

f:id:shego:20190117015913p:plain

見かけ上、線がタテ向きでも横向きでも、変更するのは「高さ」のほうです。 高さを変更しても、ハコとの接続が切れません。

ただ、よーく見ると、線の位置が中心から微妙にずれているような気がしないでもありませんが、 ちょいズレよりはマシなので気にしないようにします。

f:id:shego:20190117020513p:plain

ちょいズレコネクタがたくさんあるときにはどうすれば効率的でしょうか。

コネクタを複数選択しておけば、一括で高さを変更することが出来ます。 コネクタを複数選択するには Shift キーを押したままコネクタをクリックしていきます。

ただし、1本でも高さの違うコネクタが混ざっていると、なぜか変更できなくなるので注意が必要です。 また、コネクタがグループ化した図形に含まれていると、グループの外のコネクタを同時に選択することができないようです。

さらに問題があって、せっかくコネクタ線をきれいに直しても、接続したハコをちょっとでもいじったり自動配置し直したりすると、すぐに元の木阿弥、ちょいズレ状態に戻ってしまいます。

よほど「これが最後の仕上げ」と決めてかからないと、モグラたたきになって、また「余計な仕事」が増えるだけになります。

コネクタの種類を「直線コネクタ」に変更するには

いっそのこと、カギ線を「直線コネクタ」に変更してしまえば、もうずれることはありません。

調べてみると、線形を変更する「コネクタの変更」というコマンドがあります。 ただなぜか、リボンには見当たらず、コネクタのコンテキストメニューからしか実行できません。

ちょいズレを直線コネクタに変更するには、

  1. そのカギ線を選択して右クリックします
  2. コンテキストメニューから「コネクタの変更」→「直線コネクタ」を実行します

f:id:shego:20190106012122p:plain

カギ線は直線に置き換わり、ちょいズレなしの真っ直ぐな線になります。

ちょいズレコネクタがたくさんあるときにはどうすれば効率的でしょうか。 コネクタを複数選択して一括処理すればいいような気がしますね。

しかしやってみると、コネクタの複数選択時にはなぜか右クリックメニューから「コネクタの変更」が無くなってしまいます。

せめてショートカットがあれば素早く処理できるのですが、それもありません。 ほかにいいやり方がないかしつこく調べてみたのですが、「書式のコピー/貼り付け」では反映されない、「クイックアクセスツールバー」に登録しようにもボタンがない、「マクロの記録」をしても記録されない(!)などなど、抜け道的なワザは全て塞がれている感じです。

あまりに徹底している感じからすると、「ちょいズレ問題」はどうも不具合なんかではなく、仕様、つまり Excel さんの「本気のいやがらせ」のように思われます。 理由は良く分かりませんが、図を描くのにあまり使ってほしくないのかもしれません。

Excel の良きユーザなら、そこは尊重して無理を言わず、大人しく従っておくことにしましょう。

     



   

ちょいズレたコネクタを真っ直ぐにするマクロ

コネクタのちょいズレを真っ直ぐに矯正するマクロを作成しました。

ちょいズレを直したいコネクタを選択し、このマクロ VBA を実行すると、 その高さが 0 cm に設定され、見かけ上直線となります。 ちょいズレではない、正当なカギ線には何も影響を与えません。

コネクタを複数選択していれば、一括で処理されます。 とはいえ、コネクタは細いのでマウスで選択するのは面倒です。

本マクロでは、以下のような指定方法が可能となっています。

  • コネクタを選択
  • 接続先の図形(ハコ)を選択
  • 図形グループを選択

コネクタを複数選択するには、Shift キーを押したまま、コネクタをクリックで選択していきます。

f:id:shego:20190117012416p:plain

矩形などの図形を選択した場合、その図形に接続されたすべてのちょいズレコネクタが処理されます。 もちろん図形は複数選択が可能です。

f:id:shego:20190117012441p:plain

図形グループが選択された場合、そのグループに属するコネクタが全て処理されます。 グループ化が入れ子にされてた場合、その子グループ内のコネクタも指定されます。

f:id:shego:20190117012455p:plain

シート上の図形を全選択状態で本マクロを実行すれば、すべてのちょいズレコネクタが直ります 図形を全選択するには、何か一つ図形を選択したあとに Ctrl + A を押します。

Option Explicit

Sub コネクタのちょいズレ矯正()
    If Not hasShapeRange(Selection) Then Beep: Exit Sub
    straightenConnectors Selection.ShapeRange, 1#
End Sub

Private Sub straightenConnectors(ByVal shpRng As ShapeRange, thresholdHeight As Single)
    Dim conn As Shape
    For Each conn In collectConnectors(shpRng)
        If conn.Height <= thresholdHeight Then
            conn.Height = 0#
        End If
    Next
End Sub

Private Function collectConnectors(ByVal shpRng As ShapeRange) As Collection
    Dim selShapes As Collection
    Set selShapes = flattenShapeTree(shpRng)
    
    Dim selBoxes As Collection
    Set selBoxes = collFilter(selShapes, "isConnectable")
        
    Dim selConnectors As Collection
    Set selConnectors = collFilter(selShapes, "isConnector")
        
    Dim allConnectors As Collection
    Set allConnectors = flattenShapeTree(shpRng.Parent.Shapes)
    Set allConnectors = collFilter(allConnectors, "isConnector")
    
    Set collectConnectors = New Collection
    Dim conn As Shape
    For Each conn In allConnectors
        If collContains(selConnectors, conn) Then
            collectConnectors.Add conn
        ElseIf hasConnection(selBoxes, conn) Then
            collectConnectors.Add conn
        End If
    Next
End Function

Private Function flattenShapeTree(ByVal shps As Object) As Collection
    Dim coll As New Collection
    Dim shp As Shape, subShp As Shape
    For Each shp In shps
        If shp.Type = msoGroup Then
            For Each subShp In flattenShapeTree(shp.GroupItems)
                coll.Add subShp
            Next
        Else
            coll.Add shp
        End If
    Next
    Set flattenShapeTree = coll
End Function

Private Function hasConnection(ByVal shps As Object, ByVal aConnector As Shape) As Boolean
    hasConnection = False
    With aConnector.ConnectorFormat
        If .BeginConnected Then
            hasConnection = collContains(shps, .BeginConnectedShape)
        End If
        If .EndConnected And Not hasConnection Then
            hasConnection = collContains(shps, .EndConnectedShape)
        End If
    End With
End Function

Private Function isConnectable(ByVal shp As Shape) As Boolean
    isConnectable = 0 < shp.ConnectionSiteCount
End Function

Private Function isConnector(ByVal shp As Shape) As Boolean
    isConnector = shp.connector
End Function

Private Function collFilter(ByVal coll As Collection, pred As String) As Collection
    Set collFilter = New Collection
    Dim itm As Object
    For Each itm In coll
        If Application.Run(pred, itm) Then
            collFilter.Add itm
        End If
    Next
End Function

Private Function collContains(ByVal coll As Collection, ByVal obj As Object) As Boolean
    Dim itm As Object
    For Each itm In coll
        If obj Is itm Then
            collContains = True
            Exit Function
        End If
    Next
    collContains = False
End Function

Private Function hasShapeRange(ByVal obj As Object) As Boolean
    On Error Resume Next
    Dim shr As ShapeRange
    Set shr = obj.ShapeRange
    hasShapeRange = Not shr Is Nothing
    Err.Clear
End Function

【使い方】

  1. 上記VBAプログラムを標準モジュールにコピー&ペーストします
  2. 変換したいコネクタを選択しします
    • コネクタの接続図形やコネクタを含むグループを選択することも可能です
    • ちょいズレではないコネクタが選択に含まれていても影響ありません
  3. 変更したい線形への変換マクロを実行します

もし真っ直ぐにならないコネクタがあったら、見かけ上ちょいズレでも、正当なカギ線の折れです。 図形を中央寄せしてから、再度試してみてください。

試していませんが、たぶん、PowerPoint でも使えると思います。 試しました。ダメでした。 簡単な修正で対応できそうですが、 ちゃんと動作確認が取れるまでいったん取り下げます。

コネクタの線形を変更するマクロ

ついでに、コネクタの線形を変更するマクロも各種用意しました。

機能は Excel 本来の「コネクタの変更」と同様ですが、 コネクタの複数選択で一括処理できるところが異なります。

また、必要ならショートカットを割り付けるなど、作業の効率化が望める点も本家より便利です。

Option Explicit

Sub コネクタの変更_直線()
    If Not hasShapeRange(Selection) Then Beep: Exit Sub
    changeConnectorType Selection.ShapeRange, msoConnectorStraight
End Sub


Sub コネクタの変更_カギ線()
    If Not hasShapeRange(Selection) Then Beep: Exit Sub
    changeConnectorType Selection.ShapeRange, msoConnectorElbow
End Sub


Sub コネクタの変更_曲線()
    If Not hasShapeRange(Selection) Then Beep: Exit Sub
    changeConnectorType Selection.ShapeRange, msoConnectorCurve
End Sub

Private Sub changeConnectorType(ByVal shps As Object, connectorType As MsoConnectorType)
    Dim shp As Shape
    For Each shp In shps
        If shp.connector Then
            shp.ConnectorFormat.Type = connectorType
        End If
    Next
End Sub

Private Function hasShapeRange(ByVal obj As Object) As Boolean
    On Error Resume Next
    Dim shr As ShapeRange
    Set shr = obj.ShapeRange
    hasShapeRange = Not shr Is Nothing
    Err.Clear
End Function

【使い方】

  1. 上記VBAプログラムを標準モジュールにコピー&ペーストします
    • 先のちょいズレ矯正マクロとは別の新規標準モジュールにペーストしてください
  2. 変換したいコネクタを選択しします。
    • 複数選択するには Shiftキーを押しながらクリックしていきます
  3. 変更したい線形への変換マクロを実行します

コネクタの接続が切れる心配はありません。

コネクタ以外の図形は選択に含まれていても単に無視されます。

元に戻す(Undo)はできませんので、一括で複数コネクタを変換する場合には注意してください。

まとめ

本記事では、ちょいズレコネクタを真っ直ぐにする方法を調べました。

ちょいズレ自体困りものですが、それを修正し維持するのも大変手間のかかることだと分かりました。

Excel がなぜちょいズレ問題を放置しているのかずっと不可解でしたが、 これは不具合ではなく、甘受すべき仕様なのだということ、了解しました。

ところで、「ちょいズレ」というは説明のためにこの記事で勝手につけた呼び名なので、 常識だと勘違いしないよう念のため。

本記事の内容は Windows 10 環境の Excel 2013 で検証しました。 最新の Excel で改善されているようでしたら教えてください。

関連記事

www.shegolab.jp