【Python】PowerPointに2クリックでTeX形式を挿入するGUI【PowerPoint】

#はじめに
数式を多用するスライド資料を作るのにボタンメニューでポチポチ入力してられっかよ
って思いますよね。
とはいえパワポでTeXを使おうとすると無駄なひと手間がかかって面倒です。

こんな問題は、**ごく単純なツールを作って解決**してしまいましょう。
（Windowsのみ対応です）
#出来たもの
![ldfsi-r7a10.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501281/d3e071d2-4f79-fe22-be7d-1818969bd96c.gif)

#コード

```python
from urllib.parse import quote
from urllib.request import urlopen
import os
import tkinter
from tkinter import ttk
import pyperclip as ppc
import win32com.client
app = None
ppt = None
T = False


def setup():
    global app, ppt, T
    app = win32com.client.GetObject(Class="PowerPoint.Application")
    try:
        ppt = app.ActivePresentation
        if nop.get():
            app.CommandBars.ExecuteMso("InsertBuildingBlocksEquationsGallery")
            app.ActiveWindow.Selection.SlideRange.Shapes(
                app.ActiveWindow.Selection.SlideRange.Shapes.Count
            ).TextFrame.TextRange.Text = "Ⓣ"
            T = True
        else:
            T = False
        return True
    except:
        ppt = None
        return False


def isOpen():
    try:
        win32com.client.GetObject(Class="PowerPoint.Application")
        return True
    except:
        return False


def insertTeX():
    global index, texs
    math = tex.get("1.0", "end -1c")
    if not math or not isOpen():
        return
    if not T or not ppt or app != win32com.client.GetObject(
            Class="PowerPoint.Application"):
        if not setup(): return
    if nop.get():
        app.CommandBars.ExecuteMso("InsertBuildingBlocksEquationsGallery")
        app.ActiveWindow.Selection.SlideRange.Shapes(
            app.ActiveWindow.Selection.SlideRange.Shapes.Count
        ).TextFrame.TextRange.Text = " ".join(math.splitlines())
        app.CommandBars.ExecuteMso("EquationProfessional")
    else:
        with urlopen(
                f'https://texclip.marutank.net/render.php/texclip20201001121356.svg?s={quote(math)}&f=c&r=300&m=s&b=f&k=f'
        ) as svg:
            with open(
                    os.path.dirname(os.path.abspath(__file__)) + r"\tmp.svg",
                    "wb") as f:
                f.write(svg.read())
        app.ActiveWindow.Selection.SlideRange.Shapes.AddPicture(
            os.path.dirname(os.path.abspath(__file__)) + r"\tmp.svg", False,
            True, 0, 0)
        os.remove(os.path.dirname(os.path.abspath(__file__)) + r"\tmp.svg")
    if not texs or texs[-1] != math:
        texs.append(math)
        index += 1


def setTeX():
    tex.delete("1.0", "end -1c")
    tex.insert("1.0", ppc.paste())


def prev():
    global index
    if texs:
        index = max(index - 1, 0)
        tex.delete("1.0", "end -1c")
        tex.insert("1.0", texs[index])
    return


def next_():
    global index
    if texs:
        index = min(index + 1, len(texs) - 1)
        tex.delete("1.0", "end -1c")
        tex.insert("1.0", texs[index])
    return


main_win = tkinter.Tk()
main_win.title("TeX2PPT")
main_win.geometry("500x95")
main_win.minsize(main_win.winfo_width(), 95)

main_frm = ttk.Frame(main_win)
main_frm.grid(column=0, row=0, sticky=tkinter.NSEW, padx=5, pady=10)

index = -1
texs = []
tex = tkinter.Text(main_frm)
paste_btn = ttk.Button(main_frm, text="ペースト", command=setTeX)
insert_btn = ttk.Button(main_frm, text="挿入", command=insertTeX)
prev_btn = ttk.Button(main_frm, text="∧", command=prev, width=2)
next_btn = ttk.Button(main_frm, text="∨", command=next_, width=2)
nop = tkinter.IntVar()
nop.set(1)
rb1 = ttk.Radiobutton(main_frm, text='数式', value=1, variable=nop)
rb2 = ttk.Radiobutton(main_frm, text='画像', value=0, variable=nop)

tex.grid(column=0, row=0, sticky='nsew', rowspan=10, columnspan=10, padx=5)
paste_btn.grid(column=11, row=8, columnspan=2)
insert_btn.grid(column=11, row=9, columnspan=2)
prev_btn.grid(column=10, row=7)
next_btn.grid(column=10, row=9)
rb1.grid(column=11, row=7, sticky=tkinter.SE)
rb2.grid(column=12, row=7, sticky=tkinter.SE)

main_win.columnconfigure(0, weight=1)
main_win.rowconfigure(0, weight=1)
main_frm.columnconfigure(1, weight=1)
main_frm.rowconfigure(1, weight=1)
main_win.attributes("-topmost", True)
main_win.mainloop()
```
#使い方
・テキストボックスにTeX形式の数式を入力
・パワポの数式として挿入するか、画像化して挿入するか選択
・挿入ボタンをクリック
※数式のテキストボックスやその他のテキストボックスが選択された状態で挿入ボタンを押すと上書きされますので注意してください。

#最後に
[Desmos](https://www.desmos.com/calculator?lang=ja)なんかも数式をコピーするとTeX形式になっているので、Desmosで入力してコピー→挿入なんて使い方も便利です（むしろそれ用に作った）。