〜EXCEL2013問題〜

Excel最新版の2013ですが、購入・インストール・若干のテストはしてみたものの実用は最高で2010、どうかするとExcel2000を現役で使ってたりするするんです。
長いことこんなソフト開発をやってますと、昔作ったファイルをまだご利用いただいていたなんてことを2013で不具合発生、てんでメールをいただいて知るわけで、誠にありがたいことでございます。

さて、今回の発端は「写真貼付け1.08」がエラー発生!! の一報でございまして、よくよく聞いてみましたら2013御利用と。
で調べてみたところ・・・・ 以下本文になりますが、思い出しますのは2007騒動でございます。
あのときは大変だったなぁ・・・ またか? おまえもか? なので、このページを作ることにしました。(長い前置きだなぁ)

というわけで、情報がございましたらこちらで取り纏めいたしますので、ふるってご応募を。(なんか違う・・・)
もしかしたら解決のお役にも立てたりして。(mc_applications●yahoo.co.jpまでメールで ●?@)
EXCEL2010ネタを追加します。(2015/9/2)

目次

No
発生した問題
1.コントロールツールボックスの部品を含むシートで不具合が        
2.32Bit/64Bit 両環境でAPI関数を使いたい
3.フォームコントロールの仕様が変わったの?(2010)
4.フリーフォーム 頂点の編集で、線が勝手に曲がる(2010)
5.オートシェイプをグループ化するとずれていく?(2010)
6.

1.コントロールツールボックスの部品を含むシートで不具合が発生します。

ここは 今まで動いていたコード とやるんですが、ちょっと複雑なので、説明のためサンプルファイルを用意しました。
実際の動作でご確認下さい。

とは言っても、皆さん2013をお持ちとはかぎませんので、簡単にご説明いたします。
シート構成は標準仕様の3ページ、シート名もまんま。Excel2000で作成しました(拡張子は .xls)
Sheet1にコントロールツールボックスのチェックボックス(CheckBox1)とラベル(Label1)を配置。
こちらがエラーになりますんで、対比用にSheet2の方は、フォームコントロールからチェックボックス(チェック 1)とラベル(ラベル 1)を配置。
(ちなみにフォームのチェックボックス Trueは1、Falseは-4146でした。)

(コンボボックス(DropDown)は参考なんで、コメントアウトしてありますが、使い方次第です。)

コードの方ですが、ThisWorkBookモジュールに

Private Sub Workbook_Open()
Dim MyStr As String

'''---------------------- Excel 2013 エラー発生コード  -------------------------------------
On Error Resume Next
Sheets("Sheet1").Activate
If Err.Number <> 0 Then MsgBox "発生コード:Sheets(""Sheet1"").Activate" & vbCr & _
                    Err.Number & ":" & Err.Description & ":" & Err.HelpContext, , _
                    "コントロールツールボックス配置シートが指定できない": Err.Clear
MyStr = CStr(ActiveSheet.CheckBox1.Value)
If Err.Number <> 0 Then MsgBox "発生コード:MyStr = CStr(ActiveSheet.CheckBox1.Value)" & vbCr & _
                    Err.Number & ":" & Err.Description & ":" & Err.HelpContext, , _
                    "コントロールツールボックスの部品(CheckBox)が指定できない": Err.Clear
ActiveSheet.Label1.Caption = MyStr
If Err.Number <> 0 Then MsgBox "発生コード:ActiveSheet.Label1.Caption = MyStr" & vbCr & _
                    Err.Number & ":" & Err.Description & ":" & Err.HelpContext, , _
                    "コントロールツールボックスの部品(Label)が指定できない": Err.Clear
On Error GoTo 0
'''---------------------- Excel 2013 エラー修正コード 「フォーム」に置き換え----------------
Sheets("Sheet2").Activate
MyStr = CStr(ActiveSheet.CheckBoxes("チェック 1").Value = 1)
ActiveSheet.Labels("ラベル 1").Caption = MyStr
'With ActiveSheet.DropDowns("ドロップ 1") 'コンボボックスのコード(おまけ)
'    .List = Array("True", "False", "A", "B", "C", "D")
'    .Text = MyStr
'End With
'''------------------------ 対比コード ここまで  -----------------------------------------
End Sub

とやりました。  お察しの通り、2013ではMsgBoxが全開であります。

そもそもから、ワークシートとコントロールツールボックスの相性は悪かったんで、これをたった8個とはいえ使ってた私が悪い。
だからといってただの1個も許さん、シートも見せてやらん、全部エラーだ・・・は無いと思うなぁ。

MSの横暴は今始まったことじゃなし、納得は行きませんが、参照箇所を全部探して置き換え致します。

そうそう、一つ書き忘れ。 再現できないんで正確なメッセージ書け無くてごめんなさい。
いじってるうちにどっかで、「デザインモード」が終了できないため、シートが選択できないとか何とか言ってました。
それでコントロールに目をつけた訳っすが。

2.32Bit/64Bit 両環境でAPI関数を使いたい

こちらはもう珍しくも何ともない話題ですが、自分の心覚えとして書いときます。

キーワード「PtrSafe」を入れるんですが、入れたら入れたで、32Bitはエラーになります。
で、32Bitバージョンと64Bitバージョンを並べて #Ifつなぎと言うのが現在の対策となっております。

めちゃめちゃかっこ悪い・・・・

#If Win64 Then
    Private Declare PtrSafe Function IsClipboardFormatAvailable Lib "user32.dll" ( _
        ByVal wFormat As Long) As Long
    Private Declare PtrSafe Function OpenClipboard Lib "user32.dll" (ByVal hWnd As Long) As Long
    Private Declare PtrSafe Function GetClipboardData Lib "user32.dll" ( _
        ByVal wFormat As Long) As Long
    Private Declare PtrSafe Function CloseClipboard Lib "user32.dll" () As Long
    Private Declare PtrSafe Function OleCreatePictureIndirect Lib "olepro32.dll" ( _
        ByRef lpPictDesc As PictDesc, _
        ByRef RefIID As GUID, _
        ByVal fPictureOwnsHandle As Long, _
        ByRef IPic As IPicture) As Long  'これが要るだけ並ぶ。さらにもう1回。
#Else
    Private Declare Function IsClipboardFormatAvailable Lib "user32.dll" ( _
        ByVal wFormat As Long) As Long
    Private Declare Function OpenClipboard Lib "user32.dll" (ByVal hWnd As Long) As Long
    Private Declare Function GetClipboardData Lib "user32.dll" ( _
        ByVal wFormat As Long) As Long
    Private Declare Function CloseClipboard Lib "user32.dll" () As Long
    Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" ( _
        ByRef lpPictDesc As PictDesc, _
        ByRef RefIID As GUID, _
        ByVal fPictureOwnsHandle As Long, _
        ByRef IPic As IPicture) As Long
#End If

目次へ

3.シート上のフォームコントロールの仕様が変わったの?(2010)

旧バージョン(2003)で官公庁が作成した提出書類の話で、例によってセル方眼仕様の結合セルだらけ。
これは、まぁ仕方ないものとしますが、(ええんかい)行儀よく並べられたチェックボックスの印刷に不具合が出ました。

チェックボックスのキャプションはなし、セルに文字を入力、ややセルいっぱいの感じで、今即席で作ってみましたが再現できず。
症 状
原 因
チェック欄の上下が印刷で切れる。(□→||な感じ。)十分な高さサイズがない
(表示サイズに変更があった疑い)
チェックボックスの近傍の罫線が細くなるチェックボックスの上端と罫線が干渉している。
(表示方法・位置計算に変更があった疑い)
チェックボックスの境目にある文字が一ドット位ずれて形が崩れる
一文字の中央で1ドット下がっている感じ
チェックボックスの右端とセル文字が干渉している。
(同上)

追加情報ページへ(2016/01/07)

次はオプションボタンの例。こちらはやや再現できたので、画像を付けます。
一個のセル上に2個のオプションボタンを配置、キャプションは有と無それぞれ設定しています。

オプションの丸と、キャプションの始まりが微妙に広くなって隣のセルへはみ出してます。
とりあえずは、キャプションを無しにしてセルに文字を入力、体裁を整えましたが...。

これ、2010だけなんだなぁ。
目次へ

4.フリーフォーム 頂点の編集で、線が勝手に曲がる(2010)

この症状は2007までは無かったようです。 すでにあちこちの質問サイトに報告されていますが、2013に至っても解決されていません。
再現手順と修正手順
挿入リボンから図形を選択、オートシェイプ一覧からフリーフォームを選択します。
テキトーに何点かクリックして、最後にダブルクリック、または始点に戻ると書込み終了。
書いたばかりのフリーフォームを選択し、右クリックメニューから、「頂点の編集」とやると、変形や頂点の追加ができるようになります。
2007までは、線分の途中をドラッグすると頂点が追加され、すでにある頂点をドラッグした場合はその点だけが移動していました。
2010以降は、同じように操作はできますが、線分が曲がってしまいます。 この辺りまではよく報告されているところです。
この修正には、曲がった線分を右クリックしてメニューから、「線分を伸ばす」とすると直るのですが、
右クリックの瞬間にさらに頂点が追加されて手間が増えたり、違うメニューが出たりとなかなか大変で非常にストレスが溜ります。

私もこの機能はよく使うので、どーにかならんのか?とずっと考えていたんですが、設定はいくら探しても見つけられないし。
曲がるもんはしゃーないか。 何点か曲がったら一括して真っ直ぐに直そーかと言う案ができまして。
EXCEL2010以降用対応コードの案
以下のコードをシートモジュールにでも標準モジュールにでも貼付けて下さい。
修正中のフリーフォームのそばに、丸でも四角でも起動ボタンとして配置し、マクロの登録から「PullSegment」を登録します。
曲線が増えてイラッとしたら、その起動ボタンを押します。

但し、シート上にある全てのフリーフォームから曲線を直線に直すので、残したい曲線がある場合はご注意下さい。
どの曲線を除外するというような設定はやたら面倒なことになりますので、運用に工夫が必要です。
複数階層のグループ中にあるフリーフォームも修正の対象としています。
Public Sub PullSegment()
Dim s As Shape, i As Long

For Each s In ActiveSheet.Shapes
  If s.Type = msoFreeform Then
    On Error Resume Next
    For i = 1 To s.Nodes.Count
      s.Nodes.SetSegmentType i, msoSegmentLine
    Next
    On Error GoTo 0
  ElseIf s.Type = msoGroup Then
    Get_FreeForms s
  End If
Next
EndSec:
End Sub

Private Sub Get_FreeForms(ByVal S1 As Shape)
Dim s As Shape, i As Long

For Each s In S1.GroupItems
  If s.Type = msoFreeform Then
    On Error Resume Next
    For i = 1 To s.Nodes.Count
      s.Nodes.SetSegmentType i, msoSegmentLine
    Next
    On Error GoTo 0
  ElseIf s.Type = msoGroup Then
    Get_FreeForms s
  End If
Next
End Sub
目次へ

5.オートシェイプをグループ化するとずれていく?(2010)

どういう現象?

言葉で説明するのは難しいので画像を見てください。
ずれた!!! 左がオートシェイプで描いたクレーン
んでもって右がずれてしまった。
さらにずれた!!!! 放って置くとさらにずれが広がる。
はぐれ部品を含めて一つのグループになっている。
どうなっているのか、図形の位置をイミディエイトウィンドウで確認してみる。
Left,Topは要するに左上の角からの距離である。
グループ全体はぐれ図形
Left
1105.5
1041.75
Top
205.5
150.75

いずれも、はぐれ図形の方が左上に近いことになる。
同一グループ内の部品がグループの外にあっていいものだろうか?
まったく釈然としない。

では、どういう対策がある?

1.グループ化をやめる(なんだそりゃ)
2.グループをコピー、または切り取りをかける。
形式を選択して貼り付けからPNG、GIFを選ぶ。
要するに画像にしてしまう。
うーん...VBA(マクロ)はまったく関係しない。本題からこっちもずれた。
目次へ