個人的につくったツールとかスクリプトとか (2024年)
なにこれ?
普段から自分のためとかチームのためとかで自作のツールやスクリプトを書いているのですが、それを紹介する記事です。
たいていは外に見せられるような立派なモノではないので、その中から辛うじてまだ見せられるものをまとめます。なので内容はめっちゃ薄いとおもいます。
誰のための記事なのか、役に立つのかわかりませんが自分の記録ついでに。
iOSショートカットで登録できる家計簿
Google スプレッドシートに自分の支出を記録するためのものです。
世の中にはたくさんの家計簿ツールがありますが、データが自分の手元になかったり、データ同期にお金をとられたりするのがあんまり好きじゃないので、自分でデータを管理できるような仕組みをつくってみました。
詳しくはこちらの記事に書いてます。
いずれはレシートのOCRとか電子マネーとの連携なんかもできたら嬉しいなぁとか妄想してます。
あとは Google の Gemini をつかった自然言語処理も組み込めたら便利にできないかな。
Google ドライブのフォルダをコピーする
Google ドライブ上でフォルダのコピーを行うためのスクリプトです。
Google ドライブってファイルのコピーはできてもフォルダのコピーはできないんですよね。
ダウンロードしてローカルで手直ししてアップロードすればできますが、単に面倒なことに加えて、Google Docs のファイルが Office ファイルに変換されるのが良くないのでやりません。 (ファイルのIDも変わっちゃう)
ということで、GAS (Google Apps Script) を用いて Drive 上で直接フォルダのコピーを行うスクリプトをつくりました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
function main() {
try {
var ui = SpreadsheetApp.getUi();
// コピー元のURLを入力させる
var sourceUrlResponse = ui.prompt('コピー元フォルダのURLを入力してください');
if (sourceUrlResponse.getSelectedButton() != ui.Button.OK) {
Logger.log('コピー元の入力がキャンセルされました。');
return;
}
// コピー先のURLを入力させる
var targetUrlResponse = ui.prompt('コピー先フォルダのURLを入力してください');
if (targetUrlResponse.getSelectedButton() != ui.Button.OK) {
Logger.log('コピー先の入力がキャンセルされました。');
return;
}
// URLからフォルダIDを抽出
var sourceId = extractFolderIdFromUrl(sourceUrlResponse.getResponseText());
var targetId = extractFolderIdFromUrl(targetUrlResponse.getResponseText());
if (!sourceId || !targetId) {
Logger.log('正しいURLを入力してください。');
return;
}
// フォルダをコピー
copyFolder(sourceId, targetId);
} catch (e) {
Logger.log(e.toString()); // エラーメッセージをログに出力
}
}
// フォルダURLからフォルダIDを抽出
function extractFolderIdFromUrl(url) {
var match = url.match(/[-\w]{25,}/); // フォルダIDは25文字以上のアルファベット・数字・ハイフン
return match ? match[0] : null;
}
function copyFolder(sourceFolderId, targetFolderId) {
var sourceFolder = DriveApp.getFolderById(sourceFolderId);
var targetFolder = DriveApp.getFolderById(targetFolderId);
if (isTargetFolderInSourceFolder(sourceFolder, targetFolder)) {
Logger.log("ターゲットフォルダがソースフォルダ内に含まれています。無限ループを防ぐため中止します。");
return;
}
copyFolderContents_(sourceFolder, targetFolder);
}
function copyFolderContents_(sourceFolder, targetFolder) {
var files = sourceFolder.getFiles();
while (files.hasNext()) {
var file = files.next();
file.makeCopy(file.getName(), targetFolder);
}
var subFolders = sourceFolder.getFolders();
while (subFolders.hasNext()) {
var subFolder = subFolders.next();
var newSubFolder = targetFolder.createFolder(subFolder.getName());
copyFolderContents_(subFolder, newSubFolder);
}
}
function isTargetFolderInSourceFolder(sourceFolder, targetFolder) {
var targetFolderPath = getFolderPath(targetFolder);
var sourceFolderPath = getFolderPath(sourceFolder);
return targetFolderPath.startsWith(sourceFolderPath);
}
function getFolderPath(folder) {
var path = [];
while (folder) {
path.unshift(folder.getName());
var parents = folder.getParents();
if (parents.hasNext()) {
folder = parents.next();
} else {
break;
}
}
return path.join("/");
}
なお、このスクリプトは単にフォルダをコピペしたいという需要というよりは、他の目的でつくりました。
その目的というのが「Google Drive のファイルの所有権の強引な変更」です。
大学の学科から付与されている Google Workspace アカウントがあるのですが、そちらは学部卒業後に消されてしまうようです。
Google WS のドキュメントを読む感じ、WSアカウントが削除されると自分がオーナーとなっている Drive のデータは消去されるみたいです (当たり前)。
また、これは共有中のファイルであっても、です。
したがって学科WSアカウントがオーナーになっているファイルの所有権を自分の個人用アカウントなどに譲渡しておこうとなるのですが、WSアカウントでは組織外のユーザに所有権を譲渡することができません (管理者の設定次第かも?)。
それを解決するための強引な手段として、フォルダを共有→個人アカウントでコピーを作成という手段をとってみようと考えた次第です。
ちなみに所有権を一括で変更したいなら、Drive の検索で owner:me
というオプションを入力すれば、自分がオーナーになっているものだけフィルタできます。
それらを一括選択して共有オプションから所有権を譲渡することもできます。
ただし、これはこれで一度に選択しすぎるとページが固まるので、ファイルが多いときは分割しながらやっていく必要があり大変です。また、前述の通り組織外ユーザには所有権を譲渡できません。
カラーコードの管理
Google スプレッドシートで入力したカラーコードをセルの色に反映する Google Apps Script。
Unity や Blender の制作で用いる色の管理につかおうかなと思ってつくったものです。16進数カラーコードに対応。
結局あまりつかわなかったですが、共同制作では色を扱う際に役に立つことがあるかもしれません。
16進数カラーコード以外にRGB値でも設定できるようにしてみるといいかも?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var range = e.range;
var value = range.getValue();
// 16進数カラーコードの正規表現 (先頭の#は不要)
var hexColorRegex = /^([0-9A-F]{3}|[0-9A-F]{6})$/i;
// 下のセルを取得
var nextCell = sheet.getRange(range.getRow() + 1, range.getColumn());
// セルに入力された値が16進数カラーコードかどうかを確認
if (hexColorRegex.test(value)) {
var colorCode = "#" + value;
nextCell.setBackground(colorCode);
} else if (value === "") {
// 値が空の場合、背景色をリセット
nextCell.setBackground(null);
}
}
自動で動画の顔にモザイクかける
Python の画像認識ライブラリ RetinaFace を用いて、動画に映る顔すべてにモザイクをかけるプログラムです。
実際にこのスクリプトでモザイク加工した動画を載せておきます。
イベントに参加した動画をつくる際などで写っているひとにモザイクをかけるときに、いちいち動画編集ソフトでトラッキング→モザイク処理をするのが面倒だったので自動化してみました。
たまに漏れがあったりしますが、例えば直前直後のフレームにもモザイクをかけるようにするとかで対応できるのかな?とか思います。
あるいは細かい部分は手動でやるのもいいかもです。それくらいなら手間じゃないですし。
自分で試してみたいひとはコードを Google Colab にあげているのでどうぞ。
画像処理やってくれるつよつよGPUが無料でつかえるの、いいですよね。
PDFファイルに埋め込まれている画像をファイルとして書き出す
タイトル通りですが、論文などのPDFファイルに埋め込まれている画像ファイルをつかいたいときに取り出すスクリプトです。
PyMuPDF というライブラリを使いますが、インストールは pip install PyMuPDF
なのにインポート名は fitz
というところに注意。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import os, sys
import fitz
def main(fname):
dist = os.path.splitext(fname)[0]
os.makedirs(dist, exist_ok=True) # ディレクトリが存在しない場合は作成
with fitz.open(fname) as doc:
for i, page in enumerate(doc):
for j, img in enumerate(page.get_images(full=True)):
x = doc.extract_image(img[0])
name = os.path.join(dist, f"{i:04}_{j:02}.{x['ext']}")
with open(name, "wb") as ofh:
ofh.write(x['image'])
if __name__ == "__main__":
main(sys.argv[1]) # 引数でファイルを受け取る
PDF をいい感じに扱えるフリーソフトやアプリってないですかね〜。
重いやつ、サブスクソフト、広告ソフトなどばかりでうんざりしております。特に iPad で扱いたいときに困る。
おわりに
以上、2024年につくった完全自分用のツール/スクリプトでした。
こういうのをつくるときは大抵 ChatGPT や GitHub Copilot にたたき台をつくってもらって、細かいところをカスタムするというようなつくりかたをしています。
自分の力になるのかはわかりませんが、便利なのでついつい甘えちゃいますね。