風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

エクセルでピザカッター!(画像を等しい角度で分割)

PowerPointで、丸い画像を強引に等分する方法というツイートをみかけて、ふと「エクセルでもできるんだろうか?」と思い、試してみたくなったしだいです。
残念ながらPowerPointのように手作業でも簡単にできる方法は思いつかなかったためVBAの力を借りておりますが……
動作イメージはこんな感じです*1



手っ取り早く試してみたい方へ

マクロ有効ワークシートを共有してありますので、ダウンロードしてお試し下さい。
drive.google.com
ソースコードだけ見たい方は、こちらに晒してあります

きっともっと簡便な方法もある気がするので、アドバイス歓迎です!

備忘録

はっきり言って役に立つのか何なのかという一発ネタな感じですが、作成過程で何回もはまりいくつか知見を得られましたので、おおよそはまった気づいた順に書き留めておきます。

画像はなべて96dpi

いくつかの画像をエクセルに挿入して試していたところ、元の画像のサイズ(ピクセル)通りに表示されるものと(図の書式設定でサイズをリセットしても)異なった大きさで表示されるものとがありました。
エクセルに画像を挿入する場合は元のラスタ画像ファイル(JPEG・PNG等)は解像度を96dpiで保存しておくのが良いようです。
画像を挿入した後、図の書式設定でサイズをリセット(高さ/幅の倍率を100%にする)することで元の画像と同じ大きさにできるので、その後の調整も楽になります*2

f:id:furyu-tei:20210530114458p:plain
エクセルに挿入する画像は解像度によって見え方が異なる
画像を図形でトリミングする方法

エクセルに挿入した画像は、これを選択しつつ「図の形式(Alt+JP)→トリミング(V)→図形に合わせてトリミング(S)」から図形を選ぶことで、選んだ図形でトリミングすることができます。
f:id:furyu-tei:20210530125901p:plain
また、先に図形を挿入しておいてこれを選択しつつ「図形の書式(Alt+JD)→図形の塗りつぶし(FS)→図(P)」から画像ファイルを指定して塗りつぶすことにより、図形の形に合わせて画像をトリミングすることもできます。
f:id:furyu-tei:20210530125917p:plain

手動でやる分にはどちらでも構いません。
前者の方が直感的で、いちいち画像ファイルを選択する必要もなく(一度画像ファイルを挿入しておけば後はコピペで済む)デフォルトの塗りつぶしや枠線に煩わされることもないのでおすすめでしょうか。

今回はVBAでやるためにコピー&ペーストを極力使いたくなかったので(クリップボード周りの機能は結構な頻度で失敗するため処理が煩雑になりがち・後述)後者の方法を用いています。
このため、指定したパスに実際に画像ファイルが存在する必要があります
【追記】
最初にシート間で一回だけコピー&ペーストしておけば後はShape.Duplicateで複製できることに気づいたので、マクロ有効ワークシートの方でも前者の方法に変更してあります。

#Const DuplicatePictureToMakePiece = True ' True: 元の画像を複製 / False: 1ピース毎に画像読み込み

のTrueをFalseに変更すれば、後者の方法にも戻せます。

トリミングの位置調整はむずかしい

任意の矩形を取るラスタ画像(円形に見える画像も実際のデータは通常は矩形)に対応させたかったので、矩形の外接円(半径が\frac{\sqrt{短辺^2+長辺^2}}2)を考えて、これを等しい角度の部分円でトリミングしていくことで分割する方法を取ることにしました。

とりあえず部分円のサイズを計算して調整した上で画像を挿入すると、直後は下記のようになります。
f:id:furyu-tei:20210530131933p:plain
どうやらデフォルトは図形にフィットするように画像がサイズ調整されるようですので、図の書式設定→画像の位置で幅・高さを元の画像と同じにしてやります。
f:id:furyu-tei:20210530132345p:plain
うまく切り取られているように見えます。お、これなら簡単にいくんじゃない……? と思っていた頃が自分にもありました。

同じ操作を180°よりも小さい角度の部分円でやってやると……
f:id:furyu-tei:20210530135033p:plain
こうなります……おや、画像の表示位置が……?(わかりやすいように期待している位置を半透明で重ねています)
どうやらトリミングのときには、デフォルト(トリミングの画像位置の横方向/縦方向に移動の値が0cm)では画像の中心を図形の見えている部分(部分円だと扇型の部分)を囲む矩形の中心に合わせるようになっているようです。
つまり、図形の見えている部分(扇型の部分)の表示範囲を計算して、それに合わせて画像位置の横方向/縦方向に移動の値を調整してやる必要があったのです……め、面倒くさい……。
なんでや……図形の大きさ自体は変わってないんやし、図形の中心でええやないか……せめてそっちの設定を選ばせてくれ
f:id:furyu-tei:20210530135428p:plain

部分円を囲む矩形の求め方(三角関数なんて忘れていたかった)

部分円(扇型)を囲む矩形か……とりあえず扇形の外周上の座標X・Yそれぞれの最大値と最小値を求めればよいのだろうけれど、円弧の部分はどうすれば……? ある角度範囲をとるときのsinとcosの最大値・最小値を求める必要がありそう?🤔 そんなの、数学が苦手な自分にできるわけないだろっ!😫
最初は力技で(角度を少しずつ変化させていって最大値・最小値を取得)やっていましたが、いき.xls[互換モード]@aero_iki さん助けを求めていろいろとアドバイスをいただきつつ、

なんとか解決にいたりました。

いき.xls[互換モード]さん、ありがとうございました!

図形のままだとシートの端には寄せられない

ここまでで、なんとか画像を分割できるようになりました。
このままでもよかったのですが、図形のままだと
f:id:furyu-tei:20210530143234p:plain:w350
のように、見た目には余白があるにも関わらず実際の図形はより大きい領域を占めているため、シートの端の方に寄せられない状態になります(図形や画像の座標はシートの左上が原点となっており、負の値は指定できません)。
図形のままで任意の矩形にトリミングできればよいのですが、たぶんできません(もし方法があれば教えて下さい)。

図形を画像に変換するときの問題点

そこで、図形を画像に変換してから矩形でトリミングすることを考えたのですが。
図形を選択してコピー→図 (PNG) として貼り付けると……
f:id:furyu-tei:20210530144020p:plain
のように、見えている部分だけが残る形で画像化されてしまいます。
え、待って……これってまた面倒な座標計算をしないといけない予感?🤔

そろそろ疲れていたので💦「見えている部分だけが残るのなら……残したい部分を見えるようにすればいいじゃない!」という発想のもと、図形の正方形/長方形を基準となる外接円と同じ高さ&幅にして挿入、部分円に重ね合わせてグループ化したものをコピー→図(PNG)として貼り付ける手段を取りました。
f:id:furyu-tei:20210530145329p:plain
実際の処理では矩形は透明にしていますが、矩形の場合はその状態でコピペしても元と同じ大きさとなりました

あとは、元の画像の矩形とそれぞれの部分円が重なる領域が収まる矩形領域で(実際には先の部分円の円弧座標の最大・最小を求める処理と同じ処理で、元画像の矩形と円弧の重なり部分の座標の最大・最小もいっしょに計算しています)画像を切り取れば(ShapeのPictureFormatでCrop◯◯を設定)完成です。
f:id:furyu-tei:20210530152824p:plain
まぁ画像に変換してしまうと今度は透明部分もクリックできてしまうので、これはこれで操作しづらいのですが💦

追記:トリミングしても元画像のデータは残る

「完成です」と書いておいてあれですが💦ひとつ忘れていました。
画像をトリミング(ShapeのPictureFormatでCrop○○を設定)した場合ですが、この状態で画像を選択して「図の形式(Alt+JP)→トリミング(V)→トリミング(C)」してみるとわかるように、
f:id:furyu-tei:20210531212058p:plain
切り取られた部分(灰色になっている箇所)もデータとしては残ってしまっています。

手動でなら「図の形式(Alt+JP)→図の圧縮(M)」を選択することで
f:id:furyu-tei:20210531212304p:plain
のようなダイアログが表示され、「☑ 図のトリミング部分を削除する(D)」という便利な機能も使えるのですが、残念ながらVBAからはうまく使えません。
一応「Application.CommandBars.ExecuteMso "PicturesCompress"」を実行すればダイアログが呼び出せるので、SendKeysと組み合わせることで圧縮できなくもないのですが、オプションの選択がやりにくかったりときどき失敗する等、使い勝手がよくありません

どうしようかと思ったのですが、図形を画像に変換するときの問題点ではやっかいだった「コピー→図 (PNG) として貼り付け」をもう一回行えば、見えている部分だけが残る形で画像化されるんだからこれでいいじゃない! ということに気が付きました。
実際に試してみると……
f:id:furyu-tei:20210531213302p:plain
「コピー→図 (PNG) として貼り付け」した画像(右側)はトリミングで見ても余分な箇所は残っていません。
これで無事、みかけだけではなくてちゃんとトリミングされた画像にすることができました。

VBAでクリップボードが絡む処理は鬼門

図形を画像に変換する際には、Shapeの.Copy&Worksheetの.PasteSpecialを実行しているのですが、これをそのまま行うと高確率で.Copyもしくは.PasteSpecialのいずれかでエラーが発生してしまいます。
場合によってはエラーが発生していないのにも関わらず、画像が正常に貼付けされないケースもあります。

これはコピー→ペーストの過程で行われているクリップボードの操作で発生する問題のようです。

踊るエクセル@ExcelVBAerさんのアドバイス


に参考にクリップボード関係のWinAPIを使い、クリップボードのクリア→コピー→データがクリップボードに入ったことを確認→ペースト…という手順(エラーが発生した場合はリトライ)にしてみました。
踊るエクセルさん、ありがとうございました!
追記:記事作成後のアドバイスも追加しています

ただ、いかにも冗長な処理だし、これが適切な処理なのかも自信がないしで(クリップボード関係のWinAPIをよくわかっていない)もやもやします。よりよいやり方があれば教えて下さい。
標準のメソッドを使っているのにクリップボード関係の処理は高頻度に失敗するというのがそもそも納得いかないというのもありますが

Twitter で「work」ドメインの記事を引用するとツイートが表示されなくなってしまう件

このブログは「memo.furyutei.work」のように、gTLDとして「.work」を使用しているわけですが。
Twitter にて「.work」ドメインの記事(URL)を引用してしまうと、状況によってはそのツイートが表示されないといった不具合が発生してしまう、というお話です(2021/02/11現在)。




不具合の内容

元ツイートが「.work」ドメインの記事を含む場合

「.work」ドメインの記事を引用してツイートした場合、そのツイートにリプライが付くと、元ツイートを開いたらリプライツイートも表示されます。
ここまではいいのですが、実は、

  • リプライツイート(およびリプライツリーで繋がったツイート)を開くと、(自分以外のユーザーからは)元のツイート(リプライ先・「.work」ドメインの記事を引用したもの)は見えず、「このツイートは表示できません。This Tweet is unavailable. )」状態となってしまう

という不具合が発生します。
これ、自分で見る分には普通に表示されるため、誰かに指摘されたりしないと気が付かない罠

リプライツイートが「.work」ドメインの記事を含む場合

また、Twitter のツイートに対するリプライ中に「.work」ドメインの記事(URL)を引用してしまうと、

  • 元ツイートのユーザーには通知が行かない
  • (自分以外のユーザーが)元ツイートを表示しても、「.work」ドメインの記事を引用したリプライツイートは見えず、リプライ数としてもカウントされない
    この場合も、自分で見る分には普通に表示されているので気が付きにくい
  • 当該リプライツイートにさらにリプライが付いた場合、当該ツイートは「このツイートは表示できません。This Tweet is unavailable. )」状態となってしまう
    もちろん自分では普通に見える

という不具合が発生してしまいます。
なお、 (自分以外のユーザーであっても)当該リプライツイートを直接URLを指定して開けば見ることはできます。

自分のところだけではないらしい

最初、自分のところだけかと思いましたが、gTLD「.work」を使っているサイトを3か所ほど探して試してみたところ、いずれも同様の不具合が発生していたので、少なくとも「.work」に関しては普遍的に発生するのではないかと予想しています。
他の TLD で同様の不具合が発生するかどうかまでは調べられていません。
「.work」は新gTLDと呼ばれる比較的歴史の浅いものらしいですが、そういうのが関係していたりするのですかね?

回避方法

現状、「.work」ドメインの URL は引用しないようにするしか……。
このブログの場合、もともとはてなブログなので「furyu.hatenablog.com」の方の URL を使って引用する、という手はないではないです(面倒くさいけれど……)。

Twitter さんに不具合報告はしているのだけれど


2020/12/03・12/09、2021/02/09 と、これまで都合3回この不具合に関して報告しているのだけれど、なしのつぶて……(2021/02/11現在)。

追記


やっぱりTwitterさんにスパム判定されているってことですかねぇ。
安さで判断したのが悪いって? さすがにこういう「安かろう悪かろう」は納得いかないのですが……。

Web版TwitterからFleet画像/動画をダウンロードできるユーザースクリプト

スマホ用Twitterアプリに「Fleet(フリート)」がリリースされて早三ヶ月が経とうとしていますが、未だに使い道がよくわからない風柳です、ごきげんよう。

Web版TwitterではなかなかFleetが見られるようにならないので、こっそり(?)ダウンロードツールを作って公開していたのですが、現在もまだ見られないようなので、記事でも紹介しておきます。
スマホアプリ版みたいにリアルタイムで誰が投稿しているか表示されるわけでもなく、画像/動画を別タブで開いた際も誰が投稿したものかもわかりづらいので、使い勝手としてはイマイチですが……😅

インストール方法

ユーザースクリプトとして公開しています。
[このページを参考に](https://greasyfork.org/ja)、お使いのブラウザに Tampermonkey 等のユーザースクリプトマネージャーをインストールした状態で、
greasyfork.org
のページを開いて[スクリプトをインストール]ボタンを押し、フリートキャプチャーをインストールしてください。

使い方

フォローしている方のFleet画像/動画のダウンロード方法

[Twitterのホームタイムライン](https://twitter.com/home)を開くと、上部に[Fleets 💾]のようなボタンが表示されます。

f:id:furyu-tei:20210206123026p:plain
HOME画面上のボタン

これをクリックすると、フォローしている方が公開中のFleet画像/動画をまとめて(ZIPファイルで)ダウンロードできます。
また、[Alt]+クリックで、画像/動画を別タブでまとめて開くこともできます。
ブラウザのポップアップブロックにより別タブでうまく開けない場合は、ポップアップブロックをオフにするか、あきらめてください。

ユーザーが公開中のFleet画像/動画のダウンロード方法

ユーザーのプロフィールタイムラインを開くと、その方がFleetを公開中であれば、プロフィールアイコンの周りが水色になり、同時に[Fleets 💾]のようなボタンが表示されます。

f:id:furyu-tei:20210206123913p:plain
プロフィール上のボタン

これをクリックすると、その方が公開中のFleet画像/動画をまとめて(ZIPファイルで)ダウンロードできます。

f:id:furyu-tei:20210206123802p:plain
Zipファイルサンプル

こちらも、[Alt]+クリックで、画像/動画を別タブでまとめて開くこともできます。
注意書きも同上です。

おまけ

Fleet用自作テンプレートです。ご自由にお使いください。

f:id:furyu-tei:20210206124108p:plain
フリート用テンプレート.伝言板

【お知らせ】アマゾン注文履歴フィルタが突然使えなくなるかもしれません!!

多くの方にご利用いただいている拙作「アマゾン注文履歴フィルタ」

memo.furyutei.work

ですが、Amazon.co.jp 様側のページ仕様の変更に伴い、残念ながら今後使えなくなる可能性が高いです。

現状、本拡張機能(アドオン)は、領収書ページのHTMLを用いて一括印刷やCSVダウンロード等の機能を実現しているのですが、領収書ページのフォーマットがHTMLからPDFに変わってしまったアカウントが存在するようです(2020/12下旬に確認)。今後はこの切り替えが実施されるユーザーの方が増えていくものと予想されます。

こうなると抜本的な改修が必要となってくるのですが、現状当方の所持するアカウントではまだ切り替えが行われておらず、また時間的な余裕もないことから、短期間での対応は困難です。
少なくとも、2020年分の確定申告の期間には本拡張機能は使用できないという前提で、各位対処されることをお勧めいたします。
大変ご不便をおかけしますが、ご容赦願います。

エクセルのVBAで正規表現のメソッド実行に時間がかかる現象と対策(仮)

エクセルの VBA で、正規表現(VBScript.RegExp)の .Excute メソッドを使っているプロジェクトにて、不自然に動作が重くなってしまう現象に遭遇しました。
Windows 10 Pro バージョン 2004 (OS ビルド 19041.630) 上で、Microsoft® Excel® for Microsoft 365 MSO (16.0.13328.20262) 32 ビットにて発生。

実は、以前にも同じ現象が発生していたのですが、そのときには Windows の再起動で発生しなくなったので放置していました。
しかし、今回の場合は Excel や Windows を再起動しても改善が見られなかったため、少し調べてみることにしました。




発生した状況(再現方法)

  1. 「Microsoft Excel マクロ有効ワークシート」を新規作成
  2. 標準モジュールを追加し、VBSCript.RegExp の Excute メソッドを使用しているこちらのプロジェクトのソースコードを貼付け
  3. サンプルツイートのテキスト(【】部分に隠し文あり)を選択してコピーし、A1セルに貼り付けたあと、B1セルに「=ZenDecode(A1)」のような数式を入力(画像1)
    なお、この段階では特に遅くは感じない
  4. 一度保存して閉じてから、再度開き、「セキュリティの警告」に対して [コンテンツの有効化] ボタンを押す(画像2)
f:id:furyu-tei:20201115142102p:plain
1. サンプル
f:id:furyu-tei:20201115142146p:plain
2.「セキュリティの警告 マクロが無効にされました。」表示
[コンテンツの有効化]を押した直後や、B1セルを再入力したり、A1&B1を別セルにコピーしたりすると、体感できるほどに不自然に動作が重くなってしまいました。

対策

ワークシートを作成直後には特に重くなかったのに、保存して閉じる→再度開く→[コンテンツの有効化] を実施後に重くなってしまう(その後はずっと重いままとなる)ことに気づいたので、セキュリティ関係の機能の問題ではないかとあたりをつけ、トラスト センターの「信頼できる場所」に、当該マクロ有効ワークシートの場所を追加してみました。
  1. リボンの「ファイル」メニューから、「オプション」→「トラスト センター」で [トラスト センターの設定 (T) ...] をクリック
  2. 「信頼できる場所」の [新しい場所の追加 (A) ...] で、当該ワークシートを置いてあるフォルダを指定する(必要に応じて、「□ この場所のサブフォルダーも信頼する (S)」にもチェックを入れておく)
その後、該当ワークシートで試してみると、軽快に動作するようになりました。

注意事項

  • 同様の環境であっても、現象が再現しない場合もあります
    自分のところでも、同じファイルを、別の PC 上で試しても(「信頼できる場所」に置いていないにも関わらず)特に重くなりませんでした。また、同一 PC 上であっても、ファイルの内容によっては(?)再現しない場合もあるようです。
  • 上記の対策は、マクロのセキュリティ関連の設定になるため、「信頼できる場所」に追加するフォルダについては慎重に検討するようにしてください。試して見る場合には自己責任でお願いします。
  • あくまで当方個人の環境での対策のため、同様の現象が発生していて対策通りの手順を踏んでも改善されない場合もあるかと思いますが、ご容赦願います。