前編
https://ameblo.jp/araya-benki/entry-12795889773.html
後編
https://ameblo.jp/araya-benki/entry-12796631197.html
特別編


前回までのあらすじ
前編では、openpyxlというモジュールのざっくりした使い方、
後編では、PySimpleGUIと組み合わせた完成品を公開しましたが、
最近のPySimpleGUIは、仕様が変わりまして、
31日後までに登録が必要になること、
さらに、後で調べたら、PySimpleGUIのライセンスがLGPLであること(ライセンス汚染する)、
また、ライセンス以外でも、無料版は細かな制限が発生するので、
無料で使い続けることはできることはできるのですが、
使用者にめんどくさいことを押し付けるのはいやだ!
と、そんなこんなで改良版をお送りします。

細かいことはできないけど手っ取り早くGUIを作れるappJar
appJarは、Apacheライセンス2.0です。
著作権表示と、ライセンス表示が必要だそうです。
openpyxlはMITライセンスです。
まあ、厳密にはApacheライセンスのほうが、ちょっと厳しいけど、
MITとApache2のライセンスは、汚染しないし、自由に使えるしで、いいことづくめなので、
使ってしまいましょう。

さてと、PySimpleGUIも、appJarも、おおざっぱなものしか作れないし、
もともと、GUIでさえあれば、レイアウトとかそこまで気にしていないので、
どちらを使ってもほぼ同じなので、appJarを使います。

appJarの使い方
appJarの使い方は、このページに書かれていることがすべてです。
やれることが少ない==覚えることが少なくて済む
ということなので、画面なんかてきとうでいい場合には、おすすめです。
あと、ここに書かれていないことは、これくらい?
モジュールをインストールしないと使えません。
pip install appJar

100年カレンダー作り機改良版
これを使うには、次のコマンドを打ち込む必要があります。
pip install openpyxl appJar
やっぱり必要なのが、ExcelまたはLibreOffice。
ほかのOffice製品でちゃんと使えるかどうかは、確かめていません。
(KingSoft Officeとか買う余裕ないし)。
肝心なスクリプトは、前回のものをちゃちゃっと改造してみますね。

import openpyxl
from openpyxl.styles import Font
from openpyxl.styles import Alignment
import sys
from appJar import gui

#A~Zを配列にする。A~Zは26文字
a2z=["","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
#ここからは追加させていく
i=1
j=1
while j<5:
    while i<=26:
        bufstr = a2z[j] + a2z[i]
        a2z.append(bufstr)
        i+=1
    i=1
    j+=1

#曜日を知る法則が通じないので、力技を使う。
#年,曜日
kako=[4000,0]
mirai=[-46,0]
kiroku=[2023,7]
#基準[2023,1,0,]

#関数化
def karendaa(kako,mirai,kiroku):
    #西暦か紀元前か
    def AD_BC(ahi):
        if ahi[0]<=0:
            return "B.C. "+str(abs(ahi[0])+1)
        else:
            return "A.D. "+str(ahi[0])

    #うるう判定
    def uruu_hantei(aieee):
        ughhh=False
        if aieee%4==0:
            ughhh=True
        if aieee%100==0 and aieee%400!=0:
            ughhh=False
        return ughhh

    #曜日を調整する関数
    def hiku_and_tasu(ahi):
        kiroku=[2023,7]

        while kiroku[0]!=ahi[0]:

            #なぜか過去に遡る分のうるう年だけ計算のタイミングが合わないので、
            #無理やりタイミングを合わせる
            if ahi[0]<2023 :
                if uruu_hantei(kiroku[0]-1)==True :
                    kiroku[1]-=2
                else:
                    kiroku[1]-=1
                kiroku[0]-=1
            #未来をたどる分には計算のタイミングが合う
            if ahi[0]>2023 :
                if uruu_hantei(kiroku[0])==True :
                    kiroku[1]+=2
                else:
                    kiroku[1]+=1
                kiroku[0]+=1

            if ahi[0]==2023:
                ahi[1]=0

            if ahi[0]==kiroku[0]:
                while ahi[1]<0:
                    ahi+=7
                ahi[1] = kiroku[1]%7

    #曜日を調べる
    hiku_and_tasu(kako)

    #ブック作成
    book=openpyxl.Workbook()
    #シートを作成
    sheet=book['Sheet']
    ws=book.active

    #シートのレイアウトの設定
    #横向き
    ws.page_setup.orientation = ws.ORIENTATION_LANDSCAPE
    #フッターヘッター
    #ws.oddFooter.center.text = "&[Page] / &N ページ"
    #ws.oddHeader.center.text = "一覧表"
    #作ったものに合わせて縮小しない
    ws.sheet_properties.pageSetUpPr.fitToPage = False
    #余白(単位はインチ 1inch=2.54cm)
    ws.page_margins.top = 0.7874
    ws.page_margins.left = 0.7480
    ws.page_margins.bottom = 0.7874
    ws.page_margins.right = 0.7480
    #わからない設定。いるのだろうか?
    ws.print_options.horizontalCenterd = True
    ws.print_options.verticalCenterd = True

    #高さ、幅の大きさ変更
    #何ページ分作るかのカウンター
    peezi={"zissaino_kaunto":0,"peezisuu":0}

    #カレンダー作成用
    gatu=[None,31,28,31,30,31,30,31,31,30,31,30,31]
    koyomi=[None,"1 January","2 February","3 March","4 April","5 May","6 June","7 July","8 August","9 September","10 October","11 November","12 December"]
    sitiyou=["S","M","T","W","T","F","S"]
    nengappi=[kako[0],1,1,kako[1] ]

    #なぜかは知らないけど、
    #forやwhileで規定数回して高さを変更することができない
    #どういうわけか、全部指定することはできる。
    sheet.row_dimensions.width = 16.2857

    def seru_no_reiauto():
        #お目当ての年の1月1日の曜日を取得しなければならなくなった

        buf_array=[ nengappi[0] ,0]

        m=0
        while m<2:
            k=0
            while k<6:

                #列の幅を変更(ABC・・・)1≒0.1958cm
                j=0
                i=1
                while j<7:
                    while i<=7:
                        sheet.column_dimensions[ a2z[i+j*8] ].width = 2.84
                        i+=1
                    i=1
                    j+=1
                    if j!=6:
                        sheet.column_dimensions[ a2z[j*8] ].width = 0.82

                #行の高さを変更(123・・・)1≒0.035cm
                buf_int = (32*abs(peezi["zissaino_kaunto"]))+1
                buf_str = ("A{0}:AU{1}").format(buf_int , buf_int)
                sheet.row_dimensions[buf_int].height = 22.8571

                #セルの書式
                so1=Font(size=14,bold=True)
                so2=Font(size=11,bold=True,color='ff000000')
                so3=Font(size=11,bold=True,color='ffff0011')
                so4=Font(size=11,bold=True,color='ff2200ff')
                so5=Font(size=11,bold=False,color='ff000000')
                so6=Font(size=11,bold=False,color='ffff0011')
                so7=Font(size=11,bold=False,color='ff2200ff')
                align = Alignment(horizontal='center', vertical='center')

                #セルの書式設定と一部セル埋め
                ws["A"+str(abs(peezi["zissaino_kaunto"])*32+1)].font=so1
                ws["A"+str(abs(peezi["zissaino_kaunto"])*32+1)].alignment=align
                ws["A"+str(abs(peezi["zissaino_kaunto"])*32+1)]=AD_BC(nengappi)
                #セルの結合
                sheet.merge_cells(buf_str )

                #月
                buf_str=a2z[8*k+1]+str(abs(2+(16*(m+peezi["peezisuu"]*2))))
                buf_str2=a2z[8*k+7]+str(abs(2+(16*(m+peezi["peezisuu"]*2))))
                sheet.merge_cells(buf_str+":"+buf_str2 )

                ws[buf_str].font=so2
                ws[buf_str].alignment=align
                ws[buf_str]=koyomi[nengappi[1] ]
                #曜日のセル書式
                buf_str = a2z[8*k+1] +str(abs( 3+(16*(m+peezi["peezisuu"]*2))))
                ws[buf_str].font=so3
                ws[buf_str].alignment=align
                buf_str2 = a2z[8*k+7] +str(abs( 3+(16*(m+peezi["peezisuu"]*2)) ))
                ws[buf_str2].font=so4
                ws[buf_str2].alignment=align
                i=2
                while i<=6:
                    ws[ a2z[ 8*k + i]+str(abs( 3+(16*(m+peezi["peezisuu"]*2))) )].font=so2
                    ws[ a2z[ 8*k + i]+str(abs( 3+(16*(m+peezi["peezisuu"]*2))) )].alignment=align
                    i+=1
                #七曜
                i=1
                while i<=7:
                    ws[ a2z[ 8*k + i ]+str(abs( 3+(16*(m+peezi["peezisuu"]*2)) ))]=sitiyou[i-1]
                    i+=1
                #カレンダー部分の色分け用のセル設定
                i=4
                while i<=9:
                    buf_str = a2z[ 8*k+1 ] + str(abs( i+(16*(m+peezi["peezisuu"]*2)) ))
                    ws[buf_str].font = so6
                    ws[buf_str].alignment=align
                    i+=1

                i=4
                while i<=9:
                    buf_str = a2z[ 8*k+1 +6 ] + str(abs( i+(16*(m+peezi["peezisuu"]*2))) )
                    ws[buf_str].font=so7
                    ws[buf_str].alignment=align
                    i+=1
                j=0
                i=4
                while j<5:
                    while i<=9:
                        buf_str = a2z[ 8*k + j+2 ] + str(abs( i+(16*(m+peezi["peezisuu"]*2)) ))
                        ws[buf_str].font=so5
                        ws[buf_str].alignment=align
                        i+=1
                    i=4
                    j+=1
                j=0

                #月に応じた日数を取得する
                buf_int2 = gatu[nengappi[1] ]
                uruu=False
                if nengappi[0]%4 == 0:
                    uruu=True
                if nengappi[0]%100==0 and nengappi[0]%400!=0:
                    uruu=False
                if uruu==True and nengappi[1]==2:
                    buf_int2=29

                #日数に応じてセルを埋める
                i=1
                hiku_and_tasu(buf_array)
                guhehe=abs(4+(16*(m+peezi["peezisuu"]*2)))
                if nengappi[1]==1:
                    nengappi[3]=buf_array[1]

                while i<=buf_int2:
                    buf_str = a2z[ k*8 + abs(nengappi[3])+1] + str(guhehe)
                    ws[buf_str]=i
                    nengappi[3]+=1
                    i+=1
                    if nengappi[3]>=7:
                        nengappi[3]-=7
                        guhehe+=1
                k+=1
                nengappi[1]+=1
                if nengappi[1]>12:
                    nengappi[1]-=12
            k=0
            m+=1
        m=0

         #暦を12個作ったら年月日を移動させる
        if kako[0]>mirai[0]:
            nengappi[0]-=1
        else:
            nengappi[0]+=1

    #カウント用
    while abs(peezi["peezisuu"]) <= abs(mirai[0]-kako[0]):
        seru_no_reiauto()
        if kako[0]>mirai[0]:
            peezi["peezisuu"]-=1
            peezi["zissaino_kaunto"]+=1
        else:
            peezi["peezisuu"]+=1
            peezi["zissaino_kaunto"]+=1

    #シートの中身

    #aaa="あーん、ドーナツが食べたいよう。"
    #bbb="222"
    #ws=book.active
    #ws["A1"]=aaa
    #ws["B2"]=bbb

    #シートの名前を変える
    #sheet.title='シートン博士'

    #保存
    if kako[0]<=0:
        buf_str1="BC"+str(abs(kako[0]-1))
    else:
        buf_str1=str(kako[0])

    if mirai[0]<=0:
        buf_str2="BC"+str(abs(mirai[0]-1))
    else:
        buf_str2=str(mirai[0])

    if kako[0]==mirai[0]:
        buf_str=("{0}.xlsx".format(buf_str2))
    else:
        buf_str=("{0}-{1}.xlsx".format(buf_str1,buf_str2))
    #ファイル名をつけてエクセルファイルを保存
    book.save(buf_str)

def ripureesu(bstr):
    bstr=bstr.replace("0","0")
    bstr=bstr.replace("1","1")
    bstr=bstr.replace("2","2")
    bstr=bstr.replace("3","3")
    bstr=bstr.replace("4","4")
    bstr=bstr.replace("5","5")
    bstr=bstr.replace("6","6")
    bstr=bstr.replace("7","7")
    bstr=bstr.replace("8","8")
    bstr=bstr.replace("9","9")
    bstr=bstr.replace("年","")
    bstr=bstr.replace("AD","")
    bstr=bstr.replace("A.D.","")
    bstr=bstr.replace("ad","")
    bstr=bstr.replace("a.d.","")
    bstr=bstr.replace("紀元後","")
    bstr=bstr.replace("キリスト歴","")
    bstr=bstr.replace("西暦","")
    bstr=bstr.replace("AD","")
    bstr=bstr.replace("A.D.","")
    bstr=bstr.replace("あD","")
    bstr=bstr.replace("あ。D。","")
    bstr=bstr.replace(" ","")
    bstr=bstr.replace(" ","")
    return bstr

def mainasu1(bstr):
    if ("B.C." in bstr)==True or \
     ("BC" in bstr)==True or \
     ("b.c." in bstr)==True or \
     ("bc" in bstr)==True or \
     ("BC" in bstr)==True or \
     ("B.C." in bstr)==True or \
     ("bc" in bstr)==True or \
     ("b。c。" in bstr)==True or \
     ("紀元前" in bstr)==True :
        return True
    else:
        return False

def kigenzen_kesu(bstr):
    bstr=bstr.replace("B.C.","")
    bstr=bstr.replace("BC","")
    bstr=bstr.replace("b.c.","")
    bstr=bstr.replace("bc","")
    bstr=bstr.replace("B.C.","")
    bstr=bstr.replace("BC","")
    bstr=bstr.replace("b。c。","")
    bstr=bstr.replace("bc","")
    bstr=bstr.replace("紀元前","")
    return bstr




def tukuru():
    buf_bool=False
    try:
        str1=app.getEntry("おしっこ")
        str2=app.getEntry("うんこ")
        kako[0]=int(str1)
        mirai[0]=int(str2)
        buf_bool=True
    except :
        if str1=="" and str2=="":
            app.setLabel("9",'空欄とかだめ~!')
            buf_bool=False
        else:
            try:
                str1=ripureesu(str1)
                str2=ripureesu(str2)
                boo1=mainasu1(str1)
                boo2=mainasu1(str2)
                str1=kigenzen_kesu(str1)
                str2=kigenzen_kesu(str2)

                kako[0]=int(str1)
                mirai[0]=int(str2)
                if boo1==True:
                    kako[0]*=-1
                    kako[0]+=1
                    boo1=False
                if boo2==True:
                    mirai[0]*=-1
                    mirai[0]+=1
                    boo2=False
                buf_bool=True
            except:
                app.setLabel("9",'いや~ん! もう~! いけず~!')
                app.setEntry("おしっこ","")
                app.setEntry("うんこ","")
                buf_bool=False
    if kako[0]>mirai[0]:
        buf=kako[0]
        kako[0]=mirai[0]
        mirai[0]=buf
    if buf_bool==True:
        app.setLabel("9",'作るよ~!')
        karendaa(kako,mirai,kiroku)
        buf_bool=False
        app.setLabel("9",'できた~!')


#appJarのGUI
app=gui("カレンダーを何百年分も作る機","320x320")
app.setBg("#559955")
app.setFg("white")
app.setFont(10)

app.addLabel("-1","")
app.addLabel("0","これは過去から未来まで、指定したカレンダーの")
app.addLabel("1","エクセルファイルを作るソフトです。     ")
app.addLabel("2","過去と未来の欄に西暦を入れてね。      ")
app.addLabel("3","紀元前は「BC」を入れるかマイナス数字で。 ")
app.addLabel("4","")
app.addLabel("5","")

app.addLabel("6","過去?(半角数字で)")
app.entry("おしっこ",label=False,focus=True)
app.addLabel("11","")
app.addLabel("7","未来?(半角数字で)")
app.entry("うんこ",label=False,focus=False)
app.addLabel("8","")
app.addButtons(["作る"],tukuru)
app.addLabel("9","")
app.addLabel("10","")
#なぜか最初のフォーカス位置を設定できない
app.setFocus("おしっこ")

app.go()







参考資料

appJar(github)
https://github.com/jarvisteach/appJar/?tab=License-1-ov-file#readme

Excelからデータ抽出!Python(OpenPyXL)の読み込み方法まとめ (駆け出し物語)
http://kakedashi-xx.com:25214/index.php/2021/08/22/post-3086/