2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【VBAForm2Tkinter】VBAからドラッグ&ドロップで簡単にPython(Tkinter)のGUIを作成【使い方解説】

Last updated at Posted at 2025-09-21

以前この記事で公開したVBAのユーザーフォームをTkinterのコードに変換するツール(VBAForm2Tkinter)の使い方を解説します
作成から関数の設定までを行います
このツールを使用すれば、ドラッグ&ドロップのみで簡単にGUIのパーツ配置を行うことが可能です

1.ユーザーフォームの作成

まず、VBAで普通にユーザーフォームを作成します

img1.png

2.ツールをダウンロード

ここから最新版のSource code (zip)をダウンロードして解凍してください
この記事作成時点ではv1.1.0です

img2.png

3.VBAForm2Tkinter.basのインポート

VBA Projectと書いてある場所の何もないところを右クリックしてファイルをインポートしてください
さっき解凍したファイルにVBAForm2Tkinter.basが入っているのでそれをインポートします

img3.png
img4.png

4.変換コマンドを実行する

イミディエイトウィンドウにコマンドを入力してEnterキーを押してください
コマンドはこれです
「ユーザーフォームのオブジェクト名」のところは変換したいユーザーフォームのオブジェクト名に合わせて変えます

Call ConvertForm2Tkinter(ユーザーフォームのオブジェクト名)

画像の場合はオブジェクト名が「UserForm1」なのでユーザーフォームのオブジェクト名のところは「UserForm1」に置き換えます

Call ConvertForm2Tkinter(UserForm1)

img5.png

イミディエイトウィンドウの使い方がよくわからない人は以下のように標準モジュールにSubプロシージャを作成して実行する形でもかまいません

Sub test()
    Call ConvertForm2Tkinter(UserForm1)
End Sub

この時点でエラーが発生する場合はオブジェクト名に間違いがないか再度確認をお願いします

5.変換成功可否を確認

img6.png

変換に成功したら「Saved: 保存先」のメッセージが出現しpyファイルが保存されます、保存先はExcelブックと同じフォルダに設定されています
失敗した場合は「Control type "XXXX" is not supported」→「Conversion failed」と出ます
その場合、XXXXに当たる部分のコントロールタイプは変換非対応なので該当のコントロールを削除してからもう一度コマンドを実行してください

対応しているコントロールは以下の通りです

VBA Formのクラス Tkinterのクラス
Label tk.Label
CommandButton tk.Button
Frame tk.Frame
TextBox tk.Entry (単一行) / tk.Text (複数行)
※MultiLineに代入されたbool値により変換先を分岐
SpinButton tk.Spinbox
ListBox tk.Listbox
CheckBox tk.Checkbutton
OptionButton tk.Radiobutton
Image tk.Canvas
ScrollBar ttk.Scale
ComboBox ttk.Combobox
MultiPage ttk.Notebook

6.pyファイルを実行してみる

実行してVBAと同じ見た目か確認します
違う場合は後述の「VBAと見た目の表示が異なる場合の対処法」を参照してください
この時点ではボタンには何もイベントは登録されていません

img7.png

7.ボタンの動作を設定する

「登録」ボタンを押したらメッセージボックスに登録内容を表示するようにしてみます

import ctypes

def show_registration_info(name, email, region):
    registration_info = f"名前: {name} E-mail: {email} 地域: {region}"
    ctypes.windll.user32.MessageBoxW(None, registration_info, "登録内容", None)

生成されたコードと組み合わせます
設定内容はmainloop()の直前に記述するのがおすすめです
レイアウトを再調整する場合に再度生成したコードからtk.tk()以下、mainloopの直前をコピペすれば動作の定義まで再度しなくて済むためです

import tkinter as tk
from tkinter import ttk
from tkinter import font
import ctypes # 追加で使用するライブラリをインポート

UserForm1 = tk.Tk()
UserForm1.title("登録用フォーム")
UserForm1.geometry("304x201")
UserForm1.resizable(False, False)
UserForm1.configure(bg="#F0F0F0")
UserForm1.configure(relief=tk.FLAT, bd=0, highlightthickness=0, highlightbackground="#000000", highlightcolor="#000000")
UserForm1.configure(cursor="")

style = ttk.Style()
style.theme_use('default')

Label1 = tk.Label(UserForm1)
Label1.place(x=16, y=24, width=96, height=24)
Label1.configure(fg="#000000")
Label1.configure(bg="#F0F0F0")
Label1.configure(text="名前")
Label1.configure(font=font.Font(family="MS ゴシック", size=12))
Label1.configure(relief=tk.GROOVE, bd=2, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
Label1.configure(anchor="n")
Label1.configure(justify="center")
Label1.configure(cursor=None)

Label2 = tk.Label(UserForm1)
Label2.place(x=16, y=64, width=96, height=24)
Label2.configure(fg="#000000")
Label2.configure(bg="#F0F0F0")
Label2.configure(text="E-mail")
Label2.configure(font=font.Font(family="MS ゴシック", size=12))
Label2.configure(relief=tk.GROOVE, bd=2, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
Label2.configure(anchor="n")
Label2.configure(justify="center")
Label2.configure(cursor=None)

Label4 = tk.Label(UserForm1)
Label4.place(x=16, y=104, width=96, height=24)
Label4.configure(fg="#000000")
Label4.configure(bg="#F0F0F0")
Label4.configure(text="地域")
Label4.configure(font=font.Font(family="MS ゴシック", size=12))
Label4.configure(relief=tk.GROOVE, bd=2, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
Label4.configure(anchor="n")
Label4.configure(justify="center")
Label4.configure(cursor=None)

TextBox1 = tk.Entry(UserForm1)
TextBox1.place(x=120, y=24, width=168, height=24)
TextBox1.configure(fg="#000000")
TextBox1.configure(bg="#FFFFFF")
TextBox1.insert(0, "")
TextBox1.configure(font=font.Font(family="Arial Narrow", size=10))
TextBox1.configure(relief=tk.SUNKEN, bd=2, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
TextBox1.configure(justify="left")
TextBox1.configure(cursor=None)

TextBox2 = tk.Entry(UserForm1)
TextBox2.place(x=120, y=64, width=168, height=24)
TextBox2.configure(fg="#000000")
TextBox2.configure(bg="#FFFFFF")
TextBox2.insert(0, "")
TextBox2.configure(font=font.Font(family="Arial Narrow", size=10))
TextBox2.configure(relief=tk.SUNKEN, bd=2, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
TextBox2.configure(justify="left")
TextBox2.configure(cursor=None)

ComboBox1 = ttk.Combobox(UserForm1)
ComboBox1.place(x=120, y=104, width=168, height=24)
style.configure("ComboBox1_style.TCombobox", foreground="#000000")
style.configure("ComboBox1_style.TCombobox", fieldbackground="#FFFFFF")
ComboBox1.configure(style="ComboBox1_style.TCombobox")
ComboBox1_items_value = []
ComboBox1.configure(value=ComboBox1_items_value)
ComboBox1.set("")
ComboBox1.configure(font=font.Font(family="Arial Narrow", size=10))
ComboBox1.configure(justify="left")
ComboBox1.configure(cursor=None)

CommandButton1 = tk.Button(UserForm1)
CommandButton1.place(x=32, y=152, width=96, height=32)
CommandButton1.configure(fg="#000000")
CommandButton1.configure(bg="#00FFFF")
CommandButton1.configure(activeforeground="#000000")
CommandButton1.configure(activebackground="#00FFFF")
CommandButton1.configure(text="登録")
CommandButton1.configure(font=font.Font(family="MS ゴシック", size=12))
CommandButton1.configure(cursor=None)

CommandButton2 = tk.Button(UserForm1)
CommandButton2.place(x=160, y=152, width=96, height=32)
CommandButton2.configure(fg="#000000")
CommandButton2.configure(bg="#FF80FF")
CommandButton2.configure(activeforeground="#000000")
CommandButton2.configure(activebackground="#FF80FF")
CommandButton2.configure(text="キャンセル")
CommandButton2.configure(font=font.Font(family="MS ゴシック", size=12))
CommandButton2.configure(cursor=None)

# 関数を定義
def show_registration_info(name, email, region):
    registration_info = f"名前: {name} E-mail: {email} 地域: {region}"
    ctypes.windll.user32.MessageBoxW(None, registration_info, "登録内容", None)

# ボタンに関数を設定
CommandButton1.configure(command=lambda:show_registration_info(TextBox1.get(), TextBox2.get(), ComboBox1.get()))

UserForm1.mainloop()

8.動作を確認

再度実行してボタンを押したら、登録内容がちゃんと表示されました

img8.png

VBAと見た目の表示が異なる場合の対処法

以下のように、ボタンが隠れてしまう場合があります
これは、Tkinterでは設置順が後のものが優先して表示される仕様になっているのに対してVBAのユーザーフォームではそうとは限らないためです
変換される順番はVBAでの設置順のため、ボタンを先に設置した後にラベルを設置すると隠れてしまいます

img9.png

import tkinter as tk
from tkinter import ttk
from tkinter import font

UserForm2 = tk.Tk()
UserForm2.title("UserForm2")
UserForm2.geometry("304x201")
UserForm2.resizable(False, False)
UserForm2.configure(bg="#F0F0F0")
UserForm2.configure(relief=tk.FLAT, bd=0, highlightthickness=0, highlightbackground="#000000", highlightcolor="#000000")
UserForm2.configure(cursor="")

style = ttk.Style()
style.theme_use('default')

CommandButton1 = tk.Button(UserForm2)
CommandButton1.place(x=96, y=80, width=96, height=32)
CommandButton1.configure(fg="#000000")
CommandButton1.configure(bg="#F0F0F0")
CommandButton1.configure(activeforeground="#000000")
CommandButton1.configure(activebackground="#F0F0F0")
CommandButton1.configure(text="CommandButton1")
CommandButton1.configure(font=font.Font(family="MS UI Gothic", size=9))
CommandButton1.configure(cursor=None)

Label1 = tk.Label(UserForm2)
Label1.place(x=64, y=40, width=160, height=120)
Label1.configure(fg="#000000")
Label1.configure(bg="#00FF00")
Label1.configure(text="")
Label1.configure(font=font.Font(family="MS UI Gothic", size=9))
Label1.configure(relief=tk.FLAT, bd=0, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
Label1.configure(anchor="nw")
Label1.configure(justify="left")
Label1.configure(cursor=None)



UserForm2.mainloop()

解決方法は簡単で、ラベルの定義を先に行えばいいだけです
定義の部分だけ切り取り&貼り付けします、親コントロールの直後に定義すれば先頭に来ることはありません
定義さえ先にすればplaceは後で行っても大丈夫です

import tkinter as tk
from tkinter import ttk
from tkinter import font

UserForm2 = tk.Tk()
UserForm2.title("UserForm2")
UserForm2.geometry("304x201")
UserForm2.resizable(False, False)
UserForm2.configure(bg="#F0F0F0")
UserForm2.configure(relief=tk.FLAT, bd=0, highlightthickness=0, highlightbackground="#000000", highlightcolor="#000000")
UserForm2.configure(cursor="")

style = ttk.Style()
style.theme_use('default')

Label1 = tk.Label(UserForm2) # Label1をCommandButton1より先に定義するだけ
CommandButton1 = tk.Button(UserForm2)
CommandButton1.place(x=96, y=80, width=96, height=32)
CommandButton1.configure(fg="#000000")
CommandButton1.configure(bg="#F0F0F0")
CommandButton1.configure(activeforeground="#000000")
CommandButton1.configure(activebackground="#F0F0F0")
CommandButton1.configure(text="CommandButton1")
CommandButton1.configure(font=font.Font(family="MS UI Gothic", size=9))
CommandButton1.configure(cursor=None)

Label1.place(x=64, y=40, width=160, height=120)
Label1.configure(fg="#000000")
Label1.configure(bg="#00FF00")
Label1.configure(text="")
Label1.configure(font=font.Font(family="MS UI Gothic", size=9))
Label1.configure(relief=tk.FLAT, bd=0, highlightthickness=0, highlightbackground="#646464", highlightcolor="#646464")
Label1.configure(anchor="nw")
Label1.configure(justify="left")
Label1.configure(cursor=None)



UserForm2.mainloop()

これで正常に表示されました
img10.png

画像の設定について

img11.png

ImageオブジェクトはCanvasに変換されますが、設定してある画像までは変換されないので自分で設定を行います
生成されたコードにコメントアウトされた設定用コードがあるのでコメントアウトを解除して設定します
VBAではbmp画像を設定するのに対して、tk.PhotoImageに設定できるのはpngまたはgif画像のみなので変換を行ってください
bmp画像をペイントで開き、「名前をつけて保存」でpng画像として保存可能です

# コメントアウトを解除して画像のPathを設定(pngまたはgif)

#Image1_photo = tk.PhotoImage(file=r"")
#Image1.create_image(0, 0, image=Image1_photo, anchor=tk.NW)

# ↓ ↓ ↓

Image1_photo = tk.PhotoImage(file=r"C:\image.png")
Image1.create_image(0, 0, image=Image1_photo, anchor=tk.NW)
import tkinter as tk
from tkinter import ttk
from tkinter import font

UserForm3 = tk.Tk()
UserForm3.title("UserForm3")
UserForm3.geometry("304x201")
UserForm3.resizable(False, False)
UserForm3.configure(bg="#F0F0F0")
UserForm3.configure(relief=tk.FLAT, bd=0, highlightthickness=0, highlightbackground="#000000", highlightcolor="#000000")
UserForm3.configure(cursor="")

style = ttk.Style()
style.theme_use('default')

Image1 = tk.Canvas(UserForm3)
Image1.place(x=64, y=24, width=168, height=144)
Image1.configure(bg="#F0F0F0")
Image1.configure(relief=tk.FLAT, bd=0, highlightthickness=1, highlightbackground="#646464", highlightcolor="#646464")
Image1.configure(cursor=None)
Image1_photo = tk.PhotoImage(file=r"C:\image.png")
Image1.create_image(0, 0, image=Image1_photo, anchor=tk.NW)



UserForm3.mainloop()

これで正常に表示されました、表示位置についてはcreate_image(0, 0の0, 0(xy座標)を調整してください
img12.png

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?