先日、提示年収が最も高いプログラミング言語として、2年連続でGo言語が1位に輝いたことをpaizaが発表しました。プログラムを作っていても楽しいGo言語ですが、企業からの需要も大きいことを改めて感じるものでした。それで、今回は、Go言語の良さを確認しつつ、Go言語で来年のカレンダーを自動生成するプログラムを作ってみましょう。
企業で求められているGo言語
さて、paizaの公表した提示年収が高い言語ランキングは、企業の求人票に記載された年収を言語ごとに集計したものだそうです。1位がGo言語で711万円、2位がTypeScriptで698万円、3位がScalaで680万円だったそうです。
ここ数年、Go言語が大好きなエンジニアの皆さんは、企業でも大活躍していることでしょう。そして、本連載をご覧になる皆さんの中には、Go言語を習得して年収アップを狙いたいという方も多いことでしょう。そこで、改めてGo言語の良いところをまとめてみます。
Go言語の良いところは?
Go言語はシンプルさを重視して設計されたプログラミング言語です。提示年収が高いというと、難しい言語なのではと思いがちですが、意外にも、構文が簡潔で、比較的習得しやすい言語です。
Go言語の特徴はコンパイラ言語である点です。プログラムを実行ファイルにコンパイルしてから実行するため、高速にプログラムを実行できます。メモリ消費も少なく、組み込みの並行処理機能も備えており、効率的にプログラムを実行できるため、システムプログラミングやWebアプリ開発など、リソース効率が重要な場面で重宝されています。
クロスプラットフォームに対応している上に、外部ライブラリやランタイムを必要としない実行ファイルを生成できます。そのため、作ったプログラムの配布がとても簡単なのも、大きなメリットがあります。
Go言語でExcelファイルを生成しよう
Go言語には豊富なライブラリが存在しているのもメリットです。今回、Go言語で来年のカレンダーを記入したExcelファイルを作成しますが、Excelファイルを読み書きできるライブラリも手軽に利用できます。
Excelファイルの読み書きは、本連載で何度か紹介していますが、連載21回目で利用した「excelize」を利用します。
それでは、ターミナル(WindowsならPowerShell、macOSならターミナル.app)を起動して、以下のコマンドを実行して、プロジェクトを作成しましょう。
# プロジェクトを作成
mkdir excel_calendar
cd excel_calendar
go mod init excel_calendar
# excelizeをインストール
go get github.com/xuri/excelize/v2
上記コマンドを実行すると、Excelファイルの読み書きを行うパッケージをダウンロードして、プロジェクトに追加してくれます。
まずは、Excelファイルが正しく作成できるかテストしてみましょう。「main.go」というファイルを作成して、そこに次のプログラムを記述しましょう。
package main
import "github.com/xuri/excelize/v2"
func main() {
// 新しいExcelファイルを作成 --- (*1)
f := excelize.NewFile()
// シート名を指定してセルにデータを書き込む --- (*2)
value := "穏やかな舌は命の木である"
f.SetCellValue("Sheet1", "A1", value)
// ファイル保存 --- (*3)
f.SaveAs("test.xlsx")
println("ok")
}
プログラムを確認してみましょう。Go言語のプログラムは、main関数から始まります。そのため、ここでもfunc mainと書いてmain関数を定義します。(*1)では、新規Excelファイルを作成します。(*2)ではSheet1のセルA1に文字列を書き込みます。そして、(*3)ではExcelファイルへ保存します。このように、とても簡潔にExcelファイルの書き込みができます。
ターミナルにて、次のコマンドを実行すると「test.xlsx」というExcelファイルを生成します。
go run main.go
作成された「test.xlsx」をExcelで開くと、次のように、指定した文字列がセルA1に書き込まれたのを確認できます。
2025年の月間カレンダーを作ろう
Excelの基本的な書き込み方が分かったところで、2025年のカレンダーを作成するプログラムを作ってみましょう。ここでは、カレンダーのひな形を作っておいて、それにGo言語で日付と曜日を書き込んでみましょう。
ここでは、下記のようなテンプレート「template.xlsx」を作成しました。このテンプレートを利用して12ヶ月分の月間カレンダーを書き込みます。このテンプレートおよびプログラムをこちらにアップしています。
このひな形にカレンダーを書き込むプログラムは、次のようになります。先ほど作ったファイル「main.go」を下記のように書き換えてください。
package main
import (
"fmt"
"log"
"time"
"github.com/xuri/excelize/v2"
)
func main() {
// 初期設定 --- (*1)
year := 2025
templateFile := "template.xlsx"
weekdays := []string{"日", "月", "火", "水", "木", "金", "土"}
// ひな形ファイルを読み込む --- (*2)
xlsx, err := excelize.OpenFile(templateFile)
if err != nil {
log.Fatalf("ひな形ファイルの読み込みに失敗しました: %v\n", err)
}
// 1年分の月間カレンダ−を作成 --- (*3)
for month := 1; month <= 12; month++ {
// 対象年の開始日と終了日を取得 --- (*4)
startDate := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
endDate := startDate.AddDate(0, 1, -1) // その月の最終日
// 新規シートを作成してひな形の内容をコピー --- (*5)
sheetName := fmt.Sprintf("%d月", month)
newSheetIndex, _ := xlsx.NewSheet(sheetName)
xlsx.CopySheet(0, newSheetIndex)
// 月を指定
xlsx.SetCellValue(sheetName, "A1", month)
// カレンダーの日付と曜日を記載 --- (*6)
row := 4
for d := startDate; !d.After(endDate); d = d.AddDate(0, 0, 1) {
dateStr := d.Day()
weekdayStr := weekdays[d.Weekday()]
// セルに日付と曜日を記入 --- (*7)
a := fmt.Sprintf("A%d", row)
b := fmt.Sprintf("B%d", row)
d := fmt.Sprintf("D%d", row)
xlsx.SetCellValue(sheetName, a, dateStr)
xlsx.SetCellValue(sheetName, b, weekdayStr)
// 週末であれば背景色を変更 --- (*8)
if weekdayStr == "土" {
setCellBackgroundColor(xlsx, sheetName, a, d, "#E0E0FF")
}
if weekdayStr == "日" {
setCellBackgroundColor(xlsx, sheetName, a, d, "#FFE0E0")
}
row++
}
}
// シートのテンプレートを削除
xlsx.DeleteSheet("Sheet1")
// ファイル保存 --- (*9)
if err := xlsx.SaveAs("calendar.xlsx"); err != nil {
log.Fatalf("%v\n", err)
}
println("ok")
}
// 背景色を変更する関数 --- (*10)
func setCellBackgroundColor(f *excelize.File, sheet, cell1, cell2, color string) {
// 既存のスタイルを取得
styleId, _ := f.GetCellStyle(sheet, cell1)
style, _ := f.GetStyle(styleId)
// 背景色を変更
style.Fill.Color = []string{color}
// 新しいスタイルを作成
newStyleID, _ := f.NewStyle(style)
// 新しいスタイルをセルに適用
if err := f.SetCellStyle(sheet, cell1, cell2, newStyleID); err != nil {
log.Printf("スタイルの適用に失敗しました: %v", err)
}
}
プログラムを確認してみましょう。少し長くなりましたが、基本的には、Excelのひな形を読み込み、ひな形を新規シートにコピーして、そこにカレンダーの日付や曜日を書き込むというものになっています。
(*1)では作成するカレンダーの西暦年やひな形ファイルのパスを指定します。(*2)ではひな形となるExcelファイルを読み込みます。(*3)では1月から12月まで繰り返し処理を行います。(*4)では、対象年の開始日と終了日を計算します。(*5)では新規シートを作成して、ひな形の内容をコピーします。(*6)ではカレンダーの日付を書き込みます。(*7)では実際にセルに日付や曜日を記入します。(*8)では週末の場合に、セルの背景色を変更します。(*9)ではExcelファイルを保存します。(*10)では背景色を手軽に変更する関数を定義します。
もう少し、突っ込んで、日付処理について確認してみましょう。Go言語で2025年1月1日の曜日を調べるプログラムは、次のようになります。
// 2025年1月1日の日付を作成
date := time.Date(2025, time.January, 1, 0, 0, 0, 0, time.Local)
// 曜日を取得
weekday := date.Weekday()
jaWeek := []string{"日", "月", "火", "水", "木", "金", "土"}
weekdayStr := jaWeek[weekday]
// 結果を表示
fmt.Printf("2025年1月1日は%s(%d)です。\n", weekdayStr, weekday)
上記を、main.goのmain関数に記述して実行してみましょう。すると、次のように表示されます。
2025年1月1日は水(3)です。
time.Dateを利用するとTime型のオブジェクトが得られます。そして、Weekdayメソッドによって曜日番号が得られます。それで、曜日番号と文字列スライスを使って、日、月、火…と日本語の曜日を得ることができます。
プログラムを実行してみよう
それでは、実際にプログラムを実行してみましょう。ターミナルで下記のコマンドを実行します。すると、「calendar.xlsx」というExcelファイルが生成されます。
go run main.go
作成したExcelファイルを開くと、月ごとのカレンダーが作成されてるのを確認できます。
なお、ターミナルで次のコマンドを実行すると、実行ファイル「excel_calendar.exe」(macOSなら「excel_calendar」)が生成されます。実行ファイルに変換してしまえば、外部ライブラリへの依存がないので、配布がとても簡単です。手軽にカンレダーを作成するツールとしてみんなに使ってもらえます。