Author Archives: Colo

Office2016導入への道(1)-慣れ親しんだMDI形式をどうするか?

ようやく社内のMicrosoft Officeバージョンアップの予算がとれ、全ての端末がMicrosoft Office 2016へとアップデート予定の目処が立ちました。めでたし、めでたし。

とは簡単にいかない事情が、実はあるんです。それは・・・
今まで使っていたOfficeのバージョンが古すぎるんです。なんとOffice2003。
ということで、運用が安定するまでは色々な問題が出てきそうです。

現段階で出てきた問題を列挙してみると・・・

(問題1)MDI形式が開けない!PDFの変わりにMDI形式を社内標準としていたので。
(問題2)OWCがなくなっている!(知ってましたが、目を閉じてました。)
(問題3)他のアプリとの連携の問題が!

とまだまだ出てきそうなのですが、今回は(問題1)に焦点を当ててみようかと思います。

MDI形式はご存じない方もいらっしゃるかと思うのですが、Office2003で存在していましたOffice Document Image Writer(以下MODI)で書き出した際に出来上がるファイルの形式で、当時はPDFのように変更できないファイルを作成するために利用していました。
しかし、このMODIはMicrosoft Office 2010で削除されてしまいました・・・。

その為、Microsoft Office 2016でも当然の如くサポートされていません。Windows7以降ではMicrosoft XPS Document Writerが標準で搭載されているので、MIDIに代わりこちらの形式での運用にするか、もしくはPDF形式での運用にするのが現実的と言えます。

既存のMDIファイルに関しての問題が出てくるのですが、こちらに関しては全てのファイルをXPS形式もしくはPDF形式に変換するのが良いのですが、外部メディアに保存目的で保管されているものもあり、とてつもないファイル数になりますので、現実的ではありません。(やりたくもありません)

そこで下記のリンクのようにMODIを追加で入れてやる必要があります。因みに私は方法2のSharePoint Designer2007から入れています。

https://support.microsoft.com/ja-jp/help/982760/install-modi-for-use-with-microsoft-office-2010

Sharepoint Designer 2007のカスタムインストールダイアログ
※このスクリーンショットではOffice Document Image WriterとPicture Managerのみをインストールしています。

64ビット版のWindowsにも混在しているのですが、MODIはにMicrosoft Office 2016の64bit環境にはインストールできないようですので、32bit版を入れるようにしています。(こちらはまだ試していませんが)

64 ビット Visual Basic for Applications の概要

私は社内の端末をハンドリングする立場にあるのですが、社内にはOSは統一されているものの、64ビット環境と32ビット環境が混在する状態になってきています。そこで気をつけたいのがインストールするofficeのバージョンです。

Office Proffesuional Plus 2016を例にとってみるとビットにより二つのバージョンが存在します。そしてOSが64bitの場合はどちらでもインストールが可能です。

・Office Proffesuional Plus 2016 32bit
・Office Proffesuional Plus 2016 64bit

もちろん64bitの方が基本的な面においてはポテンシャルが高く、扱えるデータ量もそのメモリに比例して大きくなっています。ですのでスタンドアローンで他のPCとの整合性をあまり考えなくとも良い場合は64bitのインストールをしておけばいいのですが、従来の32bit環境で開発したものを色々と使いまわしする際には注意が必要です。

具体的にはVBA内での変数の扱いも変わってきますので、注意する必要が出てきます。
下記リンクの一読をお勧めいたします。

64 ビット Visual Basic for Applications の概要
https://msdn.microsoft.com/library/gg264421.aspx

VBAで.net風のコントロールを使ってみたい

cellmasters.netのColoです。最近は情報過多の社会ですので大抵の事がWEBで検索すれば、なんらかの答えに辿り着く事ができます。そして多くの人が求めている答えに関しては、既に多くの回答が見つかるでしょう。どれが正解という事はありませんが、アプリケーションの使い方を熟知した人が書いたコードはやはりシンプルでスマートなものです。そんな検索結果に出会いたいものですね。

さて.netで開発をしているとリッチで手軽なコントロールに目が慣れてきます。WEBサイトですら最近は昔と比べると華やかですよね。私はVBA大好きですので大抵の事はVBAからのアプローチを試みるのが好きなのですが、同じ事をやっているはずなのに洗練された見た目の.netだとなんとなく凄く見えてしまうものです。たとえばUserformで利用するコマンドボタンのデザインや機能です。VBAのコマンドボタンは昔ながらのデザインで、マウスオーバーしてもなんら反応もしてくれません。ちょっと寂しいですね。

001

とはいえエクセルのVBAから.NET Frameworkのパーツを使う事はできません。一部の機能は使えますがかなり限定的です(今回はここでは触れませんが)。では.netでコードを書いてUIを作成し、そこからエクセルをコントロールすればいいじゃないか?という意見もあるかと思いますが、今回の趣旨はエクセルのVBAで.net風のボタンを使う、つまりパーツを「デザイン」し創意工夫で乗り切ろう!というのが主題になります。

おそらくVBAをお使いの多くの方がお察しの通り、今回の目的の実現にはLabelコントロールのPictureプロパティを利用します。そしてVBAではあまりぱっとした使い道が思いつかないクラスモジュールを使って、お手軽でスタイリッシュな「コマンドボタン風ラベル」を作ってみることにします。

それでは準備に入りましょう。

まず準備するものは、フォームを挿入しUserForm1という名前になっていることを確認してください。その上に3つのLabelコントロールを置いてから次の3つのボタンイメージをPictureプロパティから読み込んでおきましょう。(1)デフォルト、(2)MouseOver(マウスが上に乗っかったとき)、(3)MouseDown(マウスのボタンが押されたとき)終わりましたらそれぞれの(オブジェクト名)をlb_btn01、lb_btn02、lb_btn03と変更し、LabelのVisibleプロパティをFalseにしておきます。これで実行時にはこれらのLabelは表示されません。ユーザーフォームの邪魔にならないところにでも置いておいてください。

次にコマンドボタン代わりに使いたいラベルを追加します。追加後(オブジェクト名)をbtnから始まるものに変更しておきます。あとは下記のUserForm1のコードを貼り付けます。フォームの準備はこれで完了です。

次にクラスモジュールを挿入します。(オブジェクト名)をLabelButtonClassとしてください。
ここにはLabelButtonClass以下のコードを貼り付けてください。


《材料》 ※[ブラケット]内はオブジェクト名

  • クラスモジュール [LabelButtonClass] – 1個
  • フォーム [UserForm1] – 1個
  • ボタンのデザイン画像 – 3個 (JPEGやGIFなど)
  • Labelコントロール – 3個
    オブジェクト名は下記の様に変更します。
    Label [lb_btn01]・・・デフォルトのデザインをPictureプロパティで設定
    Label [lb_btn02]・・・MouseOverのデザインをPictureプロパティで設定
    Label [lb_btn03]・・・MouseDownのデザインをPictureプロパティで設定

《コード》

'===============================================
'Form Module : UserForm1
'Labelコントロールをボタンのように利用するクラス
'===============================================

Option Explicit

'Classのメソッドを使う為のダミー
Dim myControl As New LabelButtonClass

Private Sub UserForm_Initialize()
'Labelボタンをクラス(LabelButtonClass)に登録
    myControl.SetLabelButtons Me
End Sub

Private Sub UserForm_Terminate()
'登録したもののあと始末
    Set myControl = Nothing
End Sub

Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'LabelボタンのPictureプロパティ初期化
    myControl.Initialize
End Sub

Private Sub btn_01_Click()
    MsgBox "Clicked"    'クリック時のコード
End Sub

Private Sub btn_02_Click()
    MsgBox "Clicked"    'クリック時のコード
End Sub

Private Sub btn_03_Click()
    MsgBox "Clicked"    'クリック時のコード
End Sub

Private Sub btn_04_Click()
    MsgBox "Clicked"    'クリック時のコード
End Sub

'===============================================
'Class Module : LabelButtonClass
'Labelコントロールをボタンのように利用するクラス
'===============================================

Option Explicit

'イベントドリブンを拾えるように、WithEventsで宣言
Private WithEvents LabelButton As MSForms.Label
Private LabelBtns As New Collection
Dim ActiveForm As Object
Dim LabelControls() As New LabelButtonClass

Public Sub SetMyButton(NewButton As MSForms.Label)
'ユーザーフォーム起動時のLabelボタン登録用
    Set LabelButton = NewButton
    Set ActiveForm = LabelButton.Parent
End Sub

Private Sub LabelButton_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'共通MouseUpイベント
    LoadPicture 1, LabelButton
End Sub

Private Sub LabelButton_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'共通MouseMoveイベント
   LoadPicture 2, LabelButton
End Sub

Private Sub LabelButton_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'共通MouseDownイベント
    LoadPicture 3, LabelButton
End Sub

Private Sub LoadPicture(ByVal Mouse_Event As Integer, ByVal LabelCaller As MSForms.Label)
'共通Pictureプロパティ変更
    Initialize
    LabelCaller.Picture = ActiveForm.Controls("lb_btn0" & Mouse_Event).Picture
    LabelCaller.Tag = 1
End Sub

Public Sub Initialize()
'    LabelボタンのPictureプロパティ初期化
'コレクションをループ
    Dim btn As MSForms.Label
    For Each btn In LabelBtns
        If btn.Tag = 1 Then
            btn.Picture = ActiveForm.lb_btn01.Picture
            btn.Tag = 0
        End If
    Next
End Sub

Public Sub SetLabelButtons(TargetForm As Object)
'Labelボタンをクラス(LabelButtonClass)に登録
    Dim btn As Control, i As Integer
    Set ActiveForm = TargetForm
    For Each btn In ActiveForm.Controls
        If TypeName(btn) = "Label" Then
            If btn.Name Like "btn*" Then
                ReDim Preserve LabelControls(i)
                LabelControls(i).SetMyButton btn
                'Labelボタンのリストをコレクションとして追加
                LabelBtns.Add btn
                i = i + 1
            End If
        End If
    Next
End Sub


サンプルブックのダウンロードはこちら