tag:blogger.com,1999:blog-41331682873849040962024-02-18T00:59:36.775+09:00ひこざるさんhikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.comBlogger89125tag:blogger.com,1999:blog-4133168287384904096.post-41384979728506665282023-02-19T18:19:00.003+09:002023-02-23T11:27:19.631+09:00Googleフォトに保存されているデータ数を把握する方法<h2 style="text-align: left;">概要</h2>
<p>Googleフォトにバックアップされている画像枚数を調べる方法を紹介する。</p>
<p>なお、<a href="https://blog.hikozaru.com/2020/11/GooglePhotosCapacityEstimation.html" target="_blank">「Googleフォトに保存されているデータ容量を調べる」</a>で紹介している方法ではデータをすべてダウンロードする際などに必要になる容量を確認できる。</p><p>容量ではなく、画像の枚数に関してはいくつかの方法で確認することができるが、それぞれ表示される値が異なります。</p>
<blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">
<p style="text-align: left;"><a href="#GoogleDashboard">1.Googleダッシュボードでの確認</a></p>
<p style="text-align: left;"><a href="#AndroidGmail">2.AndroidスマホのGmailアプリなどで確認</a></p>
<p style="text-align: left;"><a href="#GoogleAccount">3.Googleアカウント画面での確認</a></p>
<p style="text-align: left;"><a href="GoogleTakeout">4.GoogleTakeoutでダウンロードして確認</a>(調査中)</p>
<p></p></blockquote>
<p>以降ではそれぞれの確認方法を説明します。</p>
<h2 id="GoogleDashboard" style="text-align: left;">1.Googleダッシュボードでの確認</h2>
<blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">
<h3 style="text-align: left;">確認手順</h3>
<ol>
<li>Safari、Chrome、EdgeなどのWEBブラウザで <a href="https://myaccount.google.com/dashboard/">https://myaccount.google.com/dashboard/</a> にアクセスする</li>
<li>「フォト」欄の「xxx,xxx以上 枚の写真」を確認する。</li>
</ol>
<h3 style="text-align: left;">結果</h3>
<p>300,000以上 枚の写真</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik02RBaU53GWCXZSCZKSGmU6cW-FAan1vJ7a7IRQAkfiENCrnlVJb0ARlpzwtZZQWyONxi0PbOaIjE6h-gRoPwBnpd_SiOyN1KQur0T5mWe59WsKEPrhi8zDoK_6nosQMv4ED1zaC24jCsKG9XN0wAqySXWyBew0b465n4YnxjeTKHzN5ggu5BlH51cA/s1064/dashboard.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="578" data-original-width="1064" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEik02RBaU53GWCXZSCZKSGmU6cW-FAan1vJ7a7IRQAkfiENCrnlVJb0ARlpzwtZZQWyONxi0PbOaIjE6h-gRoPwBnpd_SiOyN1KQur0T5mWe59WsKEPrhi8zDoK_6nosQMv4ED1zaC24jCsKG9XN0wAqySXWyBew0b465n4YnxjeTKHzN5ggu5BlH51cA/s320/dashboard.png" width="320" /></a></div>
<h3 style="text-align: left;">考察</h3>
<p>枚数が少ないうちは正確な数値を確認できるかもしれませんがここでの枚数確認は使い物になりません。</p>
</blockquote>
<h2 id="AndroidGmail" style="text-align: left;">2.AndroidスマホのGmailアプリなどで確認</h2>
<blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">
<h3 style="text-align: left;">確認手順</h3>
<ol>
<li>AndroidのGmailアプリを起動</li>
<li>新規メール作成</li>
<li>画面上のクリップアイコンを選択</li>
<li>「ファイルを添付」を選択</li>
<li>「他のアプリでファイルを探す」の中に表示されている「フォト」を選択</li>
<li>「写真を選択」画面の「写真」項目の「xxx,xxx個の項目」を確認する。</li>
</ol>
<h3 style="text-align: left;">結果</h3>
<p>324,012個の項目</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVakxHiUyD30JVsLCBnvufvAeeGM1MoL8HO89bM_Ys8JMmsua-sELUImavTOwd1kONqCm1zO4e8BX-akGqmzgiErpSDANiY45Mj9_iXwF17G8eXcVd1F9qQjfs1lyE_9wur8cESX7h6qasdFSSKX--wEFTZOqzahcq8b-SCbLvFUjZl2JZTzc0cMwZeA/s480/AndroidGmail.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="161" data-original-width="480" height="107" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVakxHiUyD30JVsLCBnvufvAeeGM1MoL8HO89bM_Ys8JMmsua-sELUImavTOwd1kONqCm1zO4e8BX-akGqmzgiErpSDANiY45Mj9_iXwF17G8eXcVd1F9qQjfs1lyE_9wur8cESX7h6qasdFSSKX--wEFTZOqzahcq8b-SCbLvFUjZl2JZTzc0cMwZeA/s320/AndroidGmail.png" width="320" /></a></div>
<h3 style="text-align: left;">考察</h3>
<p>ダッシュボードよりは具体的な数値が表示される。 なお、Googleから教えたもらった内容によると、「Gmail では添付できないタイプのデータである場合は、 Gmail アプリでは検出できずに数値に含まれない可能性がございます。」とのことですが、、、Googleドライブからも同じ手順で確認できて、同じ数値が表示されます。なので添付できない画像があるというリクツは成り立たない感じです。</p></blockquote>
<h2 id="GoogleAcount" style="text-align: left;">3.Googleアカウント画面での確認</h2>
<blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">
<h3 style="text-align: left;">確認手順</h3>
<p><span style="color: red;"><b>※ アカウントを削除する前の確認画面なので最新の注意を払って操作してください。</b></span></p>
<ol>
<li>Safari、Chrome、EdgeなどのWEBブラウザで <a href="https://myaccount.google.com/deleteaccount">https://myaccount.google.com/deleteaccount</a> にアクセスする</li>
<li>「このコンテンツがすべて削除されます」の中を確認</li>
<li>「フォト」の項目「xxx,xxx 枚の写真が削除されます」や「他 xxx,xxx件」を確認する。</li>
</ol>
<h3 style="text-align: left;">結果</h3>
<p>334,044枚の写真 </p>
<p>他 334,041件</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu7Ej_UQ8-jdF2bT2EVySXVpssUtcb7yVL45DTAeSVKbpE8X9FPsINDmEeREPSFOVBN_1Il6mTFeC--ilWWTKo0R2GvQkr_qv_Ce2QQyhaxaOCKb1vyxSGzsC0S9daJERhqeQJR481vjJFHRgKWD_d_xRaSGBH3vzZo18vHR8Bbur_3V2AToOrTlsxFA/s893/GoogleAccount.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="484" data-original-width="893" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu7Ej_UQ8-jdF2bT2EVySXVpssUtcb7yVL45DTAeSVKbpE8X9FPsINDmEeREPSFOVBN_1Il6mTFeC--ilWWTKo0R2GvQkr_qv_Ce2QQyhaxaOCKb1vyxSGzsC0S9daJERhqeQJR481vjJFHRgKWD_d_xRaSGBH3vzZo18vHR8Bbur_3V2AToOrTlsxFA/s320/GoogleAccount.png" width="320" /></a></div>
<h3 style="text-align: left;">考察</h3>
<p>この方法で確認した数値が一番大きいが、「他 XXX,XXX件」と表示されている枚数は何なのか謎が多い。もしかしたらここで表示されているのはGoogleフォトだけではなく、Bloggerなどで使用している画像データの枚数も合算されている可能性がある。</p></blockquote>
<h2 id="GoogleTakeout" style="text-align: left;">4.GoogleTakeoutでダウンロードして確認(調査中)</h2>
<blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">
<h3 style="text-align: left;">確認手順[T.B.D.]</h3>
<ol>
<li>GoogleTakeout画面に遷移</li>
<li>Googleフォト以外のみにチェックを入れる</li>
<li>自動的に作成された年毎のアルバムにチェックを入れる</li>
<li>アーカイブにもチェックを入れる</li>
<li>必要であればゴミ箱にもチェックを入れる</li>
<li>Exportする</li>
</ol>
<h3 style="text-align: left;">結果</h3>
<p>T.B.D.</p>
<h3 style="text-align: left;">考察</h3>
<p>T.B.D.</p>
</blockquote>
<h2 style="text-align: left;">結論</h2>
<p>GoogleTakeoutでの確認が完了していないが、枚数が少ないときはGoogleダッシュボードで確認できる、ある程度以上枚数が多くなったときは、AndroidのGmailアプリで確認するか、アカウント削除確認画面で確認するしかない感じです。</p>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-41909326061764261972022-12-26T18:52:00.008+09:002022-12-27T10:07:36.248+09:00Google Oneを安く契約する方法
<h2>GoogleOneを 100GB月200円で契約する方法</h2>
GoogleOneは契約方法によって値段が違います、まったく同じサービスが提供されるのであれば少しでも安い方が良いです。どの方法で契約しても手間は変わらないのでぜひ安い方法で契約してください。
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4TrefVAufpvueUhFLBaTkVrfmloClwblRdkMVLLihfpQL_DgGLPpF5_4akA005DAp1AyJ9p4R1iLrUoAH2uf0kbAqjw8n2ZdcopJ8wjuo6vxuKjlyDXyrSD408mZlpyScLSRK7lpAFlb5cYuYtgUr-ubGtdj8UN0s-RUe9KUbNx8OB-b4VTEUczU0bQ/s831/FB18D42F-0691-4088-BA04-9DC953C94C08.jpeg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="831" data-original-width="831" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4TrefVAufpvueUhFLBaTkVrfmloClwblRdkMVLLihfpQL_DgGLPpF5_4akA005DAp1AyJ9p4R1iLrUoAH2uf0kbAqjw8n2ZdcopJ8wjuo6vxuKjlyDXyrSD408mZlpyScLSRK7lpAFlb5cYuYtgUr-ubGtdj8UN0s-RUe9KUbNx8OB-b4VTEUczU0bQ/s320/FB18D42F-0691-4088-BA04-9DC953C94C08.jpeg" width="320" /></a></div>
<br />
<h2>結論:iPhoneのGmailアプリで契約すると¥200/月</h2>
<ol style="text-align: left;">
<li>iPhoneのGmailアプリの右上のアカウントアイコンをタップ</li>
<li>「15GBのストレージのXX%を使用してます」をタップ</li>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVY1EnfN9HMFfG89G4Ghx4qon1PjRWkM6T_c2PmEV7AlK8OKYrryTQFLkbk7nU4rgX2q1abZcP5smX1kRrVPgB3oIyDeTuDnv0FhMFXW5zIC9I-KjkSTs2PO1dKm9nOf487Dx1Ws-WhGjFbSo5w7RVW4FMvNB46FLrU_I0rRyWRaGU0mPDQJqPB4VQzQ/s2208/9A6541E9-606B-4195-80FE-A8A671141A5F.jpeg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVY1EnfN9HMFfG89G4Ghx4qon1PjRWkM6T_c2PmEV7AlK8OKYrryTQFLkbk7nU4rgX2q1abZcP5smX1kRrVPgB3oIyDeTuDnv0FhMFXW5zIC9I-KjkSTs2PO1dKm9nOf487Dx1Ws-WhGjFbSo5w7RVW4FMvNB46FLrU_I0rRyWRaGU0mPDQJqPB4VQzQ/s320/9A6541E9-606B-4195-80FE-A8A671141A5F.jpeg" width="180" /></a></div>
<li>料金が表示されますが、なぜか¥200/月という最安値</li>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnCiunI9Dji3RnEusxA-tKYTK92Dv5eqGZkuYTc7xiAleoGBuvtSTV_UUi7zbr0bqDulS_E8qNKXDV7efSomi1zB34m_KwWrb21PJFfp8vqwzc-xZnyWAZvmkbg731jby73aNHM4-aut8FZt5hyHr5MmEbVXPMKoiQ9DjK39jwYTHTCAZnK0gfSi-FDg/s2208/F3715C18-B69A-45CA-9D8A-4DBF51976839.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnCiunI9Dji3RnEusxA-tKYTK92Dv5eqGZkuYTc7xiAleoGBuvtSTV_UUi7zbr0bqDulS_E8qNKXDV7efSomi1zB34m_KwWrb21PJFfp8vqwzc-xZnyWAZvmkbg731jby73aNHM4-aut8FZt5hyHr5MmEbVXPMKoiQ9DjK39jwYTHTCAZnK0gfSi-FDg/s320/F3715C18-B69A-45CA-9D8A-4DBF51976839.png" width="180" /></a></div>
</ol>
<h2>Googleフォトアプリ経由だと¥240/月</h2>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNcDyvC45rHHMcw3lPSDvd7wfpyUt5qkWGVPfjQN8dU7kz2rzzYb4Rr7V8HDgKuqZ0sQgytFoth-7S0_Ug-M55aY8bTg--gXOfEE4n0-R7D9659bANrglQIzLUetmR6ouUY6PRqaSjn6PQglh3zyc5nl6Myd6GSzW9xhcz_1f7duuJ4oFhAnzJCrxwng/s2208/E5BB760A-8E3F-4986-8099-3A6354EF367D.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNcDyvC45rHHMcw3lPSDvd7wfpyUt5qkWGVPfjQN8dU7kz2rzzYb4Rr7V8HDgKuqZ0sQgytFoth-7S0_Ug-M55aY8bTg--gXOfEE4n0-R7D9659bANrglQIzLUetmR6ouUY6PRqaSjn6PQglh3zyc5nl6Myd6GSzW9xhcz_1f7duuJ4oFhAnzJCrxwng/s320/E5BB760A-8E3F-4986-8099-3A6354EF367D.png" width="180" /></a></div>
<h2>GoogleOneアプリ経由だと通常価格の¥250/月</h2>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9y0Jzd7AyEv6tjPeqpWwC8bJ3cjaX-4U98fgOVMN7EI7F7RoreGZfSonRPwUc_aC57pW_jFoLrS2EwmVWzrdNoJapVKl5qrn0VPLbPnX2OGdMhpjpARGm-V98htJlzm2M9oFGJqGhJklGyHTIE35HNo6p5gzrOekcmUkONufbjmGN56XPDdXc0QQtaw/s2208/B204F9FF-E01A-4873-B72F-E5199BD81AAA.png" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9y0Jzd7AyEv6tjPeqpWwC8bJ3cjaX-4U98fgOVMN7EI7F7RoreGZfSonRPwUc_aC57pW_jFoLrS2EwmVWzrdNoJapVKl5qrn0VPLbPnX2OGdMhpjpARGm-V98htJlzm2M9oFGJqGhJklGyHTIE35HNo6p5gzrOekcmUkONufbjmGN56XPDdXc0QQtaw/s320/B204F9FF-E01A-4873-B72F-E5199BD81AAA.png" width="180" /></a></div>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-54503275372342491782022-11-29T19:59:00.006+09:002023-01-04T12:46:45.839+09:00Google Formsでドロップダウン形式の日付を毎日変更する<h2 style="text-align: left;">背景</h2><div>グーグルフォームのGASで自動で毎日ドロップダウン形式の日付が変わる仕組みの<a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12271368237" target="_blank">質問</a>&<a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12271331827" target="_blank">質問</a>があり、リファレンスマニュアルをみてなんとなくできそうなことはわかっていたが、実際に作ってみた。</div><div><br /></div><h2 style="text-align: left;">ソースコート</h2><pre class="src">function updateForm() {
// 毎日実行するトリガを設定
setTrigger( arguments.callee.name );
var forms = FormApp.getActiveForm();
var items = forms.getItems();
var table = [
{'title':'発症日','start':-14 ,'end':0 }, // 二週間前から今日まで
{'title':'診察希望日1','start':7 ,'end':1 }, // 7日後から明日まで(逆順)
{'title':'診察希望日2','start':1 ,'end':7 } // 明日から7日後まで
];
// 途中に日付が変わると面倒なのでここで取得
var today = new Date();
items.forEach( (item) =>{
table.forEach( (range) =>{
// リスト形式で質問がテーブルのtitleと一致したときに処理
if( item.getType() == FormApp.ItemType.LIST && item.getTitle() == range.title )
{
item = item.asListItem();
var choices = [];
// テーブルの内容に従い選択肢を追加
var dir = (range.start<range.end)?1:-1;
for( var i = range.start; (range.start<=i&&i<=range.end)||(range.end<=i&&i<=range.start); i += dir )
{
var day = new Date( today );
day.setDate(today.getDate() + i);
choices.push( item.createChoice(formatDate( day, "yyyy/MM/dd" )));
}
item.setChoices(choices);
}
});
});
}
function formatDate (date, format) {
format = format.replace(/yyyy/g, date.getFullYear());
format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2));
format = format.replace(/dd/g, ('0' + date.getDate()).slice(-2));
format = format.replace(/HH/g, ('0' + date.getHours()).slice(-2));
format = format.replace(/mm/g, ('0' + date.getMinutes()).slice(-2));
format = format.replace(/ss/g, ('0' + date.getSeconds()).slice(-2));
format = format.replace(/SSS/g, ('00' + date.getMilliseconds()).slice(-3));
return format;
}
function setTrigger(name) {
// 念のため既存のトリガはすべて削除してから次のトリガーを設定する
var triggers = ScriptApp.getProjectTriggers();
triggers.forEach( (trigger) =>{
if( trigger.getHandlerFunction() == name )
{
ScriptApp.deleteTrigger(trigger);
}
});
var setTime = new Date();
setTime.setDate(setTime.getDate() + 1)
setTime.setHours(12);
setTime.setMinutes(00);
ScriptApp.newTrigger(name).timeBased().at(setTime).create();
}</pre>
<h2 style="text-align: left;">フォームに追加したプルダウン</h2><div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7OLJNe4cszzZ6R9GzaEUSpR61a6o0JYHCdw4-6qXkglRRWZUAZmGqpmVap7clZih84sIPQue8_hsPeQ8py-7WEHPKmCeLAi-pInX267WOvbhLFHLk8QbYczUi_wYmh0JipgvBvRsy3RGXQZskjH2monZ4F_beCNvpkF_AWfq6NCfKusUTi_Yns3CPfA/s825/%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="825" data-original-width="649" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7OLJNe4cszzZ6R9GzaEUSpR61a6o0JYHCdw4-6qXkglRRWZUAZmGqpmVap7clZih84sIPQue8_hsPeQ8py-7WEHPKmCeLAi-pInX267WOvbhLFHLk8QbYczUi_wYmh0JipgvBvRsy3RGXQZskjH2monZ4F_beCNvpkF_AWfq6NCfKusUTi_Yns3CPfA/s320/%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3.PNG" width="252" /></a></div><br /><br /></div></div>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-35943644769117595982022-11-20T13:22:00.005+09:002022-11-23T18:15:52.575+09:00GoogleTakeoutでダウンロードしたGoogleフォト画像のファイルタイムスタンプを修正するプログラム<div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGaXrum12E5AmhXFOgtoK3n3Xd4A9j3KUE4pbSFDn8yTkpvPJN6j9pZ3DqghAvJDeaKw4GUM1FTVn3oAWK1XgwLqX2k6-tvFkaoZ6bX_TzqZ-P5OClvbXKleKhkZeuFMzwmIlBUR1G3pmBablKOUbWTw9_vNpuuHSVsPbWD6p4wmtRmsZWasDHA4Yy/s427/%E7%94%BB%E5%83%8F1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="425" data-original-width="427" height="199" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGaXrum12E5AmhXFOgtoK3n3Xd4A9j3KUE4pbSFDn8yTkpvPJN6j9pZ3DqghAvJDeaKw4GUM1FTVn3oAWK1XgwLqX2k6-tvFkaoZ6bX_TzqZ-P5OClvbXKleKhkZeuFMzwmIlBUR1G3pmBablKOUbWTw9_vNpuuHSVsPbWD6p4wmtRmsZWasDHA4Yy/w200-h199/%E7%94%BB%E5%83%8F1.png" width="200" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div></div>
<p><a href="https://blog.hikozaru.com/2022/11/googletakeoutgoogle.html">以前の記事( https://blog.hikozaru.com/2022/11/googletakeoutgoogle.html)</a>で紹介した作業をもう少し簡単に実行できるようにプログラムを作成したのでそのソースコードを公開する。いろいろ手を抜くために邪道なこと(変数名に日本語を使う)を行っているが、気になる人は好きに修正するとよい。プロジェクト全体が欲しい方は<a href="https://github.com/hikozaru/CorrectGooglePhotosTimestamp.git" target="_blank">ここ</a>から、実行できるものが欲しい方は<a href="https://github.com/hikozaru/CorrectGooglePhotosTimestamp/blob/75470c2c0b5051eb018fd67b60df8cc0c6fd13fc/PhotosTimestamp/bin/Release/CorrectGoogleTakeoutPhotosTimestamp.exe" target="_blank">ここ</a>からダウンロードしてください。</p><div><span style="color: red;"><b>takeout機能で複数のZIPファイルに分割された場合にはすべての同一のフォルダに統合してください。</b></span>****.jpegと****.jpeg.jsonが同一フォルダに存在する場合に処理可能なのですが、****.jpegと****.jpeg.jsonが同一のZIPファイルに格納されていると限りません。</div><div><br /></div><div>該当のファイルを実行アイコンにドラッグ&ドロップするか、実行して表示されたウインドウにドラッグ&ドロップしてください。</div><div><br /></div>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkp-neT1OSxxy8eZOcvekqULLKibXrORGE37w28Ca37YiN-D4i36IqvFPU2auvwAPpOZOelD8gUoEqY6N5tADZb_81pVWlbtXkjqLcciMoomp0Ngl-GnyjykYoMYPM0hkCJKXMqfYZoC8nCyz2ZwxrExC0qGH1XNZUXE4XrnjA3ImJXqsZbxCU_OzYTA/s1186/%E5%AE%9F%E8%A1%8C%E7%94%BB%E9%9D%A2.png" style="margin-left: 1em; margin-right: 1em;">
<img border="0" data-original-height="443" data-original-width="1186" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkp-neT1OSxxy8eZOcvekqULLKibXrORGE37w28Ca37YiN-D4i36IqvFPU2auvwAPpOZOelD8gUoEqY6N5tADZb_81pVWlbtXkjqLcciMoomp0Ngl-GnyjykYoMYPM0hkCJKXMqfYZoC8nCyz2ZwxrExC0qGH1XNZUXE4XrnjA3ImJXqsZbxCU_OzYTA/w400-h150/%E5%AE%9F%E8%A1%8C%E7%94%BB%E9%9D%A2.png" width="400" /></a></div>
<br /><p>プログラムの大まかな処理の流れは以下です。</p><p></p><ol style="text-align: left;"><li>指定されたファイルもしくは指定されたフォルダ配下のファイルすべてを処理<br />ただし、JSONファイルは処理をスキップ</li><li>ファイル名の後ろに".json"を付加したファイルが存在していたらデシリアライズして撮影日時を取得<br /></li><li>撮影日時はunixtimeなのでutcを経由してローカル時間に変換</li><li>ファイルの作成日時と更新日時を変更、その処理が成功したらJSONファイルも同様に作成日時と更新日時を変更</li><li>結果をDataGridに出力</li></ol><div>JSONファイルから撮影日時を取り出してファイルのタイムスタンプを修正する処理に関連するコードはほんの一部(コードの背景色を変えた行)です。その他は操作性やエラー発生時の処理などを考慮したコードです。</div><div><br /></div><div>まだ、大量データでのテストは実施していませんが、DataGridへの出力がボトルネックとなる可能性があります。もしかしたら処理成功したファイルの表示は辞めるとか、そもそもDataGridへの出力は辞めて結果をログファイルに出力の方が良いかもしれません。</div><p></p><p><br /></p><p>まずはCSファイル</p>
<pre class="src">using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Windows;</pre><pre class="src">namespace PhotosTimestamp
{
<span style="background-color: #d0e0e3;"> [DataContract]
public class ImageInfo
{
[DataMember(Name = "photoTakenTime")]
public PhotoTakenTime PhotoTakenTime { get; set; }
}
[DataContract]
public class PhotoTakenTime
{
[DataMember(Name = "timestamp")]
public string timstamp { get; set; }
}
</span>
public partial class MainWindow : Window
{
enum E_RESULT
{
更新,
失敗,
SKIP
};
class Result
{
public int 番号 { get; set; }
public E_RESULT 結果 { get; set; }
public string ファイル名 { get; set; }
public string エラーメッセージ { get; set; }
public string 例外メッセージ { get; set; }
}
const string HowToUse
= "Google TakeoutでダウンロードしたZIPファイルを展開し、展開されたファイル/フォルダをドラッグ&ドロップして下さい。\n"
+ "コマンドライン引数やプログラムアイコンへのドラッグ&ドロップでもファイル/フォルダ指定可能です。\n"
+ "画像ファイルにJSONファイル(例:IMG_1234.PNGに対しIMG_1234.PNG.json)がある場合に処理を行います。\n"
+ "TakeoutでZIPファイルが分割された場合には一つのフォルダに統合してください、画像ファイルとJSONファイルが同一のZIPに格納されるとは限りません。\n"
+ "JSONファイルに記録されているphotoTakenTime.timestampをLocal時間に変換し、画像ファイルとJSONファイルの作成日時と更新日時に設定します。";
public MainWindow()
{
InitializeComponent();
var resultList = new ObservableCollection<result>();
resultDataGrid.ItemsSource = resultList;
}
// 引数で指定されたときは即実行
private void Window_ContentRendered(object sender, EventArgs e)
{
string[] args = Environment.GetCommandLineArgs();
if (args.Length > 1)
{
Thread thread = new Thread(new ParameterizedThreadStart(WorkerThread));
thread.Start(args.Skip(1).ToArray());
}
else
{
ddPanel.AllowDrop = true;
status.Content = HowToUse;
}
}
// Drag&Drop関連処理
private void ddPanel_PreviewDragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.None;
if (e.Data.GetDataPresent(System.Windows.DataFormats.FileDrop, true))
{
e.Effects = DragDropEffects.Copy;
e.Handled = e.Data.GetDataPresent(DataFormats.FileDrop);
}
}
private void ddPanel_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
Thread thread = new Thread(new ParameterizedThreadStart(WorkerThread));
thread.Start(e.Data.GetData(DataFormats.FileDrop));
}
}
// UIが固まらないようにThreadで処理
void WorkerThread(object arg)
{
Dispatcher.Invoke((Action)(() =>
{
ddPanel.AllowDrop = false;
status.Content = "処理開始";
var dataList = resultDataGrid.ItemsSource as ObservableCollection<result>;
dataList.Clear();
}));
DoEntries((string[])arg);
Dispatcher.Invoke((Action)(() =>
{
ddPanel.AllowDrop = true;
status.Content = "処理が終了しました。\n" + HowToUse;
}));
}
void DoEntries(string[] args)
{
foreach (string arg in args)
{
if (File.Exists(arg) == true)
{
DoFile(arg);
}
else
{
try
{
foreach (var path in Directory.GetFiles(arg, "*", System.IO.SearchOption.AllDirectories))
{
DoFile(path);
}
}
catch (Exception e)
{
Dispatcher.Invoke((Action)(() =>
{
var dataList = resultDataGrid.ItemsSource as ObservableCollection<result>;
dataList.Add(new Result() { 番号=dataList.Count+1, 結果=E_RESULT.失敗, ファイル名 = arg, エラーメッセージ="ファイルまたはフォルダが見つかりませんでした。",例外メッセージ = e.ToString() });
}));
}
}
}
}
void DoFile(string targetFilename)
{
<span style="background-color: #d0e0e3;"> var jsonFilename = targetFilename + ".json";
</span> if (string.Compare(".json", System.IO.Path.GetExtension(targetFilename), true) == 0)
{
Dispatcher.Invoke((Action)(() =>
{
status.Content = targetFilename;
}));
}
else if (System.IO.File.Exists(jsonFilename))
{
DateTime photoTakenTime;
try
{
<span style="background-color: #d0e0e3;"> using (var stream = new FileStream(jsonFilename, FileMode.Open, FileAccess.Read))
{
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(ImageInfo));
var imageInfo = (ImageInfo)serializer.ReadObject(stream);
var unixtime = imageInfo.PhotoTakenTime.timstamp;
photoTakenTime = DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixtime)).LocalDateTime;
}
var imageFile = new System.IO.FileInfo(targetFilename);
var jsonFile = new System.IO.FileInfo(jsonFilename);
</span>
var results = new Result[] {
new Result(){ 結果=E_RESULT.SKIP,ファイル名=targetFilename,エラーメッセージ="",例外メッセージ="" },
new Result(){ 結果=E_RESULT.SKIP,ファイル名=jsonFilename,エラーメッセージ="画像ファイルの更新に失敗したときはJSONファイルも更新しません。",例外メッセージ="" }
};
foreach (var result in results)
{
try
{
var file = new System.IO.FileInfo(result.ファイル名);
<span style="background-color: #d0e0e3;"> file.CreationTime = photoTakenTime;
file.LastWriteTime = photoTakenTime;
</span> result.結果 = E_RESULT.更新;
result.エラーメッセージ = "";
result.例外メッセージ = "";
}
catch (Exception e)
{
result.結果 = E_RESULT.失敗;
result.エラーメッセージ = "タイムスタンプの更新に失敗しました。";
result.例外メッセージ = e.ToString();
break;
}
}
Dispatcher.Invoke((Action)(() =>
{
status.Content = targetFilename;
var dataList = resultDataGrid.ItemsSource as ObservableCollection<result>;
foreach (var result in results)
{
result.番号 = dataList.Count + 1;
dataList.Add(result);
}
}));
}
catch(Exception e)
{
Dispatcher.Invoke((Action)(() =>
{
status.Content = targetFilename;
var dataList = resultDataGrid.ItemsSource as ObservableCollection<result>;
dataList.Add(new Result() { 番号 = dataList.Count + 1, 結果 = E_RESULT.失敗, ファイル名 = jsonFilename, エラーメッセージ = "タイムスタンプの取得に失敗しました。", 例外メッセージ = e.ToString() });
}));
}
}
else
{
Dispatcher.Invoke((Action)(() =>
{
status.Content = targetFilename;
var dataList = resultDataGrid.ItemsSource as ObservableCollection<result>;
dataList.Add(new Result() { 番号 = dataList.Count + 1, 結果 = E_RESULT.SKIP, ファイル名 = targetFilename, エラーメッセージ = "*.JSONファイルがありません。", 例外メッセージ = "" });
}));
}
}
}
}</result></result></result></result></result></result></pre>
次はXAMLファイル<pre class="src"><window contentrendered="Window_ContentRendered" height="450" mc:ignorable="d" title="Google Takeoutでダウンロードした画像のタイムスタンプをJSONファイルを参考に修正します。" width="1200" x:class="PhotosTimestamp.MainWindow" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:PhotosTimestamp" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<dockpanel allowdrop="false" drop="ddPanel_Drop" name="ddPanel" previewdragover="ddPanel_PreviewDragOver">
<label dockpanel.dock="Bottom" name="status">
<datagrid dockpanel.dock="Top" isreadonly="True" name="resultDataGrid">
</datagrid></label></dockpanel>
</window>
</pre>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com2tag:blogger.com,1999:blog-4133168287384904096.post-16201178102437370602022-11-14T08:27:00.021+09:002023-01-02T23:43:14.791+09:00GoogleTakeoutでダウンロードしたGoogleフォト画像のファイルタイムスタンプを修正する<div style="background-color: #fff2cc; text-align: left;">22022/11/20追記:PowerShellは難しいという方は<a href="https://blog.hikozaru.com/2022/11/correcttimestamp.html">次の記事</a>で専用のプログラムを<a href="https://github.com/hikozaru/CorrectGooglePhotosTimestamp/blob/75470c2c0b5051eb018fd67b60df8cc0c6fd13fc/PhotosTimestamp/bin/Release/CorrectGoogleTakeoutPhotosTimestamp.exe" target="_blank">ダウンロード</a>できるようにしています。</div><h2 style="text-align: left;">概要</h2><div>Googleフォトのデータをtakeout(<a href="https://takeout.google.com/?hl=ja">https://takeout.google.com/?hl=ja</a>)機能でダウンロードするとファイルのタイムスタンプがダウンロード実施した日になってしまう。Takeoutで出力したデータに含まれているJSONデータに撮影日時が記録されているので、その情報をもとに修正する方法を説明します。Windowsパソコンが必要です。</div><div>なお、<span style="color: red;"><b>takeout機能で複数のZIPファイルに分割された場合にはすべての同一のフォルダに統合してください。</b></span>****.jpegと****.jpeg.jsonが同一フォルダに存在する場合に処理可能なのですが、****.jpegと****.jpeg.jsonが同一のZIPファイルに格納されていると限りません。</div><div><br /></div><h2 style="text-align: left;">①PowerShellのスクリプトを実行できるようにする</h2><p>PowerShell 管理者権限として実行します。ウインドウズメニューを開いた状態で「PowerSell」と入力すると見つかるので、「管理者として実行する」を選択してください。</p><p>以下のコマンドを実行し現在の権限を確認しメモしておいてください。</p><pre>Get-ExecutionPolicy</pre><p>以下のコマンドを実行して権限を変更してください。</p><pre>Set-ExecutionPolicy RemoteSigned</pre><p>変更してよいか確認されるので Y キーを押してください。</p><p>なお、権限(RestrictedやRemoteSignedなどの)の詳細は以下を参照してください。</p><p><a href="https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.3#powershell-execution-policies">https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.3#powershell-execution-policies</a></p><p><br /></p><h2 style="text-align: left;">②スクリプトを作成</h2><p>拡張子を表示した状態で「CorrectTimestamp.ps1」というファイルを作成しメモ帳で以下の様に編集してください。</p><pre class="src">$files = Get-ChildItem $PSScriptRoot -File -Recurse -Exclude *.json,*.html,*.ps1,*.zip
foreach($i in $files){
Write-Host $i.FullName
$jsondata = Get-Content -Path $i".json" | ConvertFrom-JSON
$j = $i.FullName+".json"
$UnixTime = $jsondata.<b>photoTakenTime</b>.timestamp.Trim('"')
$UtcTime = ([DateTime]::Parse("1970/01/01 00:00:00")).addSeconds($UnixTime)
$LocalTime= [TimeZoneInfo]::ConvertTimeFromUtc($UtcTime,[TimezoneInfo]::local)
Set-ItemProperty $i -name <b>CreationTime</b> -value $LocalTime
Set-ItemProperty $j -name <b>CreationTime</b> -value $LocalTime
Set-ItemProperty $i -name <b>LastWriteTime</b> -value $LocalTime
Set-ItemProperty $j -name <b>LastWriteTime</b> -value $LocalTime
}
Write-Host "Processing has finished. Please press any key. . ." -NoNewLine
[Console]::ReadKey($true) > $null</pre><p>JSON内にはいくつかの日時が記録されております、上記のスクリプトでは<strike><span style="color: #999999;">photoLastModifiedTimeを更新日時に設定していますが、photoTakenTimeを採用するなど好みに合わせて変更してください。</span></strike>更新日時もphotoTakenTimeにしています。</p><p><br /></p><h2 style="text-align: left;">③Zipファイルの展開とスクリプトの配置</h2><p>Takeout機能でダウンロードしたZIPファイルを全て展開し、展開されたフォルダに「CorrectTimestamp.ps1」をコピーしてください。</p><p><br /></p><h2 style="text-align: left;">④スクリプトの実行</h2><p>「CorrectTimestamp.ps1」ファイルを右クリックして「PowerShellで実行」を行うとタイムスタンプが修正されます。</p><p><br /></p><h2 style="text-align: left;">その他</h2><p>JSONファイルに記録されているデータを使ってファイル名を変えたりすることもできるが、PowerShellでなくWSH(Windows Script Host)などでも処理できると思います。</p><p><br /></p><p><br /></p><p><br /></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-39234608489772038432022-10-09T14:12:00.003+09:002022-10-10T00:04:27.942+09:00バッチファイル(*.bat)でファイルをゴミ箱に入れる<h1 style="text-align: left;">バッチファイルでファイルを直接削除するのは怖いのでゴミ箱を経由する</h1><p style="text-align: left;">バッチファイルで直接ゴミ箱に入れることはできないので、WSH経由で削除します。</p><p style="text-align: left;">PowerShellを使う方法もありますが、セキュリティ的に使えない事が多いのでWSHを選択しました。<br />また、そもそも全てをWSHで実現すれば良いと思いますが、BATファイルの方が楽なケースも多いので結構役に立ちます。</p><div>sample.bat (バッチファイルサンプル)
<pre class="src">@echo on
CScript.exe trash.js c:\folder\test1.txt c:\folder\test2.txt
</pre>
</div><div>
trash.js
<pre class="src">var args = WScript.Arguments;
var sa = WScript.CreateObject("Shell.Application");
var fso = WScript.CreateObject("Scripting.FileSystemObject");
for (var i = 0; i < args.length; i++ ) {
arg = args(i);
WScript.Echo(arg);
sa.NameSpace(10).MoveHere( arg );
while( fso.FileExists( arg ) ){
WScript.Sleep(100);
}
}
// ゴミ箱の取得(NameSpace関数の10の意味)
// https://learn.microsoft.com/ja-jp/windows/win32/api/shldisp/ne-shldisp-shellspecialfolderconstants
// WScript.Echo( sa.NameSpace(10).Title );</pre>
</div>
<p style="text-align: left;">今後改善したい項目</p><ul style="text-align: left;"><li>エラー処理</li><li>相対パス指定対応</li></ul><p></p>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-91702297939218888792022-08-28T13:52:00.000+09:002022-08-28T13:52:21.359+09:00WSH(JScript)で*.xlsmを*.xlsxに変換する<p>マクロを有効にした XML ブック(*.xlsm)を既定のXML ブック(*.xlsx)に変換する。</p>
<p>xlsm2xlsx.jsのアイコンに変換したい *.xlsm ファイルを複数Drag&Dropすると *.xlsx ファイルを生成する。</p>
<h3>xlsm2xlsx.js</h3>
<pre class="code">var xlWorkbookDefault = 51;
var ExcelApp = new ActiveXObject( "Excel.Application" );
// *.jsファイルにDrag&Dropされたファイルを順番に処理
var args = WScript.Arguments;
for (var i = 0; i < args.length; i++ ) {
var orgFilename = args(i);
// 特定の拡張子のみ処理を実施
var orgExtension = orgFilename.split('.').pop();
if( orgExtension == 'xlsm' ){
var baseName = orgFilename.substring(0, orgFilename.indexOf('.'+orgExtension))
// ファイルを開いて形式を変更して保存
var book = ExcelApp.Workbooks.Open( orgFilename );
ExcelApp.DisplayAlerts= false;
book.SaveAs( baseName + '.xlsx' , xlWorkbookDefault );
ExcelApp.DisplayAlerts= true;
ExcelApp.Quit();
}
}
WScript.Echo( "finish" );
ExcelApp = null;
</pre>
<h3>参考</h3>
<p><a href="https://docs.microsoft.com/ja-jp/office/vba/api/excel.xlfileformat">https://docs.microsoft.com/ja-jp/office/vba/api/excel.xlfileformat</a></p>
<p><a href="https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook.saveas">https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbook.saveas</a></p>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-60641774500403793552022-07-03T17:28:00.012+09:002022-07-03T20:03:56.891+09:00HTML+CSSでトグルボタン<p>すぐに忘れるので画像も文字列も変化するトグルボタン。デザインは適当。</p>
<img alt="" border="0" width="320" data-original-height="230" data-original-width="270" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3GvzzP7Tmzsm_YvxOG5cdB17LMEWmdG8Z_fL9xb2lXmJDwOpy7-sKy2FW1rKoRnxJ3vX5WOhMhHsMWlMiy7240HBmIvhRzPy2zTCV0eGJJkLeAF2hBypw3jc6BdjZSzjyxV1Snj-KaY8QjYT0Uh4jW6oRyo3UdHyn16-zVDUCl6VD9Jet7tqlbF6KQA/s320/video.gif"/>
<h2>まずはコードから</h2>
<pre class="src">
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<style>
.btn,.btn:checked+label,.btn+label+label
{
display:none;
}
.btn+label,.btn:checked+label+label
{
display:inline-block;
user-select: none;
background-repeat: no-repeat;
}
.btn+label
{
background-color:aqua;
}
.btn:checked+label+label
{
background-color:pink;
}
.btn:active+label,
.btn:active+label+label
{
background-color: lightgray;
}
.vertical+label,.vertical+label+label
{
padding-top: 2em;
background-position:top;
background-size: auto 2em;
}
.horizontal+label,.horizontal+label+label
{
padding-left: 2em;
background-position:left;
background-size: 2em auto;
}
.image+label,.image+label+label
{
height: 2em;
width: 2em;
background-position:center;
background-size: contain;
text-indent:100%;
white-space:nowrap;
overflow:hidden;
}
.text+label,.text+label+label
{
background-position:center;
background-size: 0 0;
}
</style>
<table>
<TR><TH>ボタン</TH><TH>トグル</TH></TR>
<TR><TD>
<input class="btn vertical" type="button" id="1"/>
<label for="1" style="background-image:url(send.png)">メール送信</label>
<hr>
<input class="btn horizontal" type="button" id="2"/>
<label for="2" style="background-image:url(send.png)">メール送信</label>
<hr>
<input class="btn image" type="button" id="5"/>
<label for="5" style="background-image:url(send.png)">メール送信</label>
<hr>
<input class="btn text" type="button" id="6"/>
<label for="6" style="background-image:url(send.png)">メール送信</label>
<hr>
</TD>
<TD>
<input class="btn vertical" type="checkbox" id="3"/>
<label for="3" style="background-image:url(opened.png)">既読メール</label>
<label for="3" style="background-image:url(unopened.png)">未読メール</label>
<hr>
<input class="btn horizontal" type="checkbox" id="4" checked/>
<label for="4" style="background-image:url(opened.png)">既読メール</label>
<label for="4" style="background-image:url(unopened.png)">未読メール</label>
<hr>
<input class="btn image" type="checkbox" id="7"/>
<label for="7" style="background-image:url(opened.png)">既読メール</label>
<label for="7" style="background-image:url(unopened.png)">未読メール</label>
<hr>
<input class="btn text" type="checkbox" id="8"/>
<label for="8" style="background-image:url(opened.png)">既読メール</label>
<label for="8" style="background-image:url(unopened.png)">未読メール</label>
<hr>
</TD></TR>
</table>
</body>
<html>
</pre>
<h2>動作は以下のような感じ</h2>
<style>
.btn,.btn:checked+label,.btn+label+label
{
display:none;
}
.btn+label,.btn:checked+label+label
{
display:inline-block;
user-select: none;
background-repeat: no-repeat;
}
.btn+label
{
background-color:aqua;
}
.btn:checked+label+label
{
background-color:pink;
}
.btn:active+label,
.btn:active+label+label
{
background-color: lightgray;
}
.vertical+label,.vertical+label+label
{
padding-top: 2em;
background-position:top;
background-size: auto 2em;
}
.horizontal+label,.horizontal+label+label
{
padding-left: 2em;
background-position:left;
background-size: 2em auto;
}
.image+label,.image+label+label
{
height: 2em;
width: 2em;
background-position:center;
background-size: contain;
text-indent:100%;
white-space:nowrap;
overflow:hidden;
}
.text+label,.text+label+label
{
background-position:center;
background-size: 0 0;
}
</style>
<table>
<tbody><tr><th>普通のボタン</th><th>トグルするボタン</th></tr>
<tr><td>
<input class="btn vertical" id="1" type="button" />
<label for="1" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWgRQKB_eb6-bxIKRCRRk2ruzzsUk5T5hRRIZ03ye_vb_AbvG26Vsw6nQMAIZ_rM0W0pDWAbmqQ8gdXa9E17inCGyl1JT9NeFhsNF9SH71P5T8wl10ZL89m9xJlIB4nFE4RnFGjC1GetbVGSJH1xez8JVxj6fcTFceO3hpbXx7NfL3pu_KRimLBxsRcg/s96/send.png);">メール送信</label>
<hr />
<input class="btn horizontal" id="2" type="button" />
<label for="2" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWgRQKB_eb6-bxIKRCRRk2ruzzsUk5T5hRRIZ03ye_vb_AbvG26Vsw6nQMAIZ_rM0W0pDWAbmqQ8gdXa9E17inCGyl1JT9NeFhsNF9SH71P5T8wl10ZL89m9xJlIB4nFE4RnFGjC1GetbVGSJH1xez8JVxj6fcTFceO3hpbXx7NfL3pu_KRimLBxsRcg/s96/send.png);">メール送信</label>
<hr />
<input class="btn image" id="5" type="button" />
<label for="5" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWgRQKB_eb6-bxIKRCRRk2ruzzsUk5T5hRRIZ03ye_vb_AbvG26Vsw6nQMAIZ_rM0W0pDWAbmqQ8gdXa9E17inCGyl1JT9NeFhsNF9SH71P5T8wl10ZL89m9xJlIB4nFE4RnFGjC1GetbVGSJH1xez8JVxj6fcTFceO3hpbXx7NfL3pu_KRimLBxsRcg/s96/send.png);">メール送信</label>
<hr />
<input class="btn text" id="6" type="button" />
<label for="6" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWgRQKB_eb6-bxIKRCRRk2ruzzsUk5T5hRRIZ03ye_vb_AbvG26Vsw6nQMAIZ_rM0W0pDWAbmqQ8gdXa9E17inCGyl1JT9NeFhsNF9SH71P5T8wl10ZL89m9xJlIB4nFE4RnFGjC1GetbVGSJH1xez8JVxj6fcTFceO3hpbXx7NfL3pu_KRimLBxsRcg/s96/send.png);">メール送信</label>
<hr />
</td>
<td>
<input class="btn vertical" id="3" type="checkbox" />
<label for="3" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6qG6Oo0bbAE5Uq3B7BBYdJ14huljQUl0v74_5ba-uFyUqkuV4Qf2U6aOkABNs-ybIXtGN6ztvVk00eaRoB4fv9tmbtuSGZ-k0pqHanfZSOdNNTJc1Geu4ZOSSLUTZfZti30OB02WI9ZamPVr8FYAQC4X1fPzjtD-ZUNTQJBLs2y0EgnzDbLaIHgRa0Q/s96/opened.png);">既読メール</label>
<label for="3" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwwHKxrKBVBF3BHe_JxlnCh68EhpnWBwZDVfSkv5_BffSpbiH2wqsHviPzIUUDdRMtfWufm_gkmmNBZae_tp9wz7NBohhwedYUwlAEftVMm6oo7Wr_QLrefmYOEGQuJTpVX-ReGwAOf-md_SAC5JbkcSE36wP2_DsFIxwCjYH6gJfmONWVB00gblzu9w/s1600/unopened.png);">未読メール</label>
<hr />
<input checked="" class="btn horizontal" id="4" type="checkbox" />
<label for="4" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6qG6Oo0bbAE5Uq3B7BBYdJ14huljQUl0v74_5ba-uFyUqkuV4Qf2U6aOkABNs-ybIXtGN6ztvVk00eaRoB4fv9tmbtuSGZ-k0pqHanfZSOdNNTJc1Geu4ZOSSLUTZfZti30OB02WI9ZamPVr8FYAQC4X1fPzjtD-ZUNTQJBLs2y0EgnzDbLaIHgRa0Q/s96/opened.png);">既読メール</label>
<label for="4" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwwHKxrKBVBF3BHe_JxlnCh68EhpnWBwZDVfSkv5_BffSpbiH2wqsHviPzIUUDdRMtfWufm_gkmmNBZae_tp9wz7NBohhwedYUwlAEftVMm6oo7Wr_QLrefmYOEGQuJTpVX-ReGwAOf-md_SAC5JbkcSE36wP2_DsFIxwCjYH6gJfmONWVB00gblzu9w/s1600/unopened.png);">未読メール</label>
<hr />
<input class="btn image" id="7" type="checkbox" />
<label for="7" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6qG6Oo0bbAE5Uq3B7BBYdJ14huljQUl0v74_5ba-uFyUqkuV4Qf2U6aOkABNs-ybIXtGN6ztvVk00eaRoB4fv9tmbtuSGZ-k0pqHanfZSOdNNTJc1Geu4ZOSSLUTZfZti30OB02WI9ZamPVr8FYAQC4X1fPzjtD-ZUNTQJBLs2y0EgnzDbLaIHgRa0Q/s96/opened.png);">既読メール</label>
<label for="7" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwwHKxrKBVBF3BHe_JxlnCh68EhpnWBwZDVfSkv5_BffSpbiH2wqsHviPzIUUDdRMtfWufm_gkmmNBZae_tp9wz7NBohhwedYUwlAEftVMm6oo7Wr_QLrefmYOEGQuJTpVX-ReGwAOf-md_SAC5JbkcSE36wP2_DsFIxwCjYH6gJfmONWVB00gblzu9w/s1600/unopened.png);">未読メール</label>
<hr />
<input class="btn text" id="8" type="checkbox" />
<label for="8" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6qG6Oo0bbAE5Uq3B7BBYdJ14huljQUl0v74_5ba-uFyUqkuV4Qf2U6aOkABNs-ybIXtGN6ztvVk00eaRoB4fv9tmbtuSGZ-k0pqHanfZSOdNNTJc1Geu4ZOSSLUTZfZti30OB02WI9ZamPVr8FYAQC4X1fPzjtD-ZUNTQJBLs2y0EgnzDbLaIHgRa0Q/s96/opened.png);">既読メール</label>
<label for="8" style="background-image: url(https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhwwHKxrKBVBF3BHe_JxlnCh68EhpnWBwZDVfSkv5_BffSpbiH2wqsHviPzIUUDdRMtfWufm_gkmmNBZae_tp9wz7NBohhwedYUwlAEftVMm6oo7Wr_QLrefmYOEGQuJTpVX-ReGwAOf-md_SAC5JbkcSE36wP2_DsFIxwCjYH6gJfmONWVB00gblzu9w/s1600/unopened.png);">未読メール</label>
<hr />
</td></tr>
</tbody></table>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-32875737699165929542022-05-28T20:27:00.003+09:002022-11-23T09:59:16.852+09:00GASでドライブの画像を表示する<p><a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14262437569" target="_blank">知恵袋への回答</a>は質問に直接答えたが、画面ロード時に時間がかかりそうなので処理を全体的に変えてみた。</p><p><br /></p>
コード.gs
<pre class="src">function doGet(e) {
return HtmlService.createTemplateFromFile("index.html").evaluate().setTitle("タイトル");
}
function GetBase64Image(fileId,param)
{
var file = DriveApp.getFileById(fileId);
var blob = file.getBlob();
var contentType = blob.getContentType();
var base64 = Utilities.base64Encode(blob.getBytes());
var imageSrc = "data:" + contentType + ";base64, " + base64;
return {"name":file.getName(),"id":fileId,"base64":imageSrc,"param":param};
}
</pre>
index.html
<pre class="src"><html>
<head>
<script>
<?
var folder = DriveApp.getFolderById("1MdeTdaYDv9BK9QTaZes5_bTDRpKiLRnA");
var files = folder.getFiles();
var list = [];
while (files.hasNext()) {
var file = files.next();
list.push({"id":file.getId(),"name":file.getName(),"url":file.getUrl()});
}
?>
var list = <?!= JSON.stringify(list) ?>;
function onSelected(event)
{
var img = document.getElementById("image")
img.alt = "Loading....";
img.src = null;
var fileId = event.currentTarget.value;
google.script.run
.withSuccessHandler( SuccessGetBase64Image )
.withFailureHandler( Failure )
.GetBase64Image( fileId, img.id );
}
function Failure(){
alert("失敗");
}
function SuccessGetBase64Image(entry)
{
document.getElementById(entry.param).alt = entry.name;
document.getElementById(entry.param).src = entry.base64;
}
function onLoad()
{
var select = document.getElementById("select");
select.addEventListener('change', onSelected);
list.forEach( file => {
var option = document.createElement("option");
option.value = file.id;
option.innerText = file.name;
select.appendChild(option);
});
}
</script>
</head>
<body onload="onLoad();">
<label for="select">Choose a menu:</label>
<select name="select" id="select">
<option value="">--Please choose an option--</option>
</select>
<p><img src="" height="562" width="750" alt="選択されてません" align="top" id="image">ここに画像表示</p>
</script>
</body>
</html></pre>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-23977224797185155762022-05-14T13:08:00.014+09:002022-05-14T20:05:19.574+09:00JavaScriptで○×ゲームを作ってみた
<div>JavaScriptでcanvasを使って、三目並べの○×ゲームを作ってみた。</div>
<div><a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14261746649">https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14261746649</a></div>
<div>canvasで作るよりもTableやButtonで作った方が大分楽。</div>
<!-------------------------------->
<canvas id="sampleCanvas"></canvas>
<script>
let canvas;
let context;
let Magnification = 100;
let Finished = false;
let FirstStrike=true;
let MarubatsuTable={};
function drawFrame()
{
// #を描画
context.beginPath();
context.moveTo(Magnification*0, Magnification*1);
context.lineTo(Magnification*3, Magnification*1);
context.moveTo(Magnification*0, Magnification*2);
context.lineTo(Magnification*3, Magnification*2);
context.moveTo(Magnification*1, Magnification*0);
context.lineTo(Magnification*1, Magnification*3);
context.moveTo(Magnification*2, Magnification*0);
context.lineTo(Magnification*2, Magnification*3);
context.stroke();
}
function onClick(e)
{
if( Finished )
{
context.clearRect(0, 0, canvas.width, canvas.height);
drawFrame();
MarubatsuTable = {};
Finished = false;
FirstStrike = true;
return;
}
// クリックされたセルを検出
let rect = e.target.getBoundingClientRect();
let x = Math.floor( (e.clientX - rect.left) / Magnification );
let y = Math.floor( (e.clientY - rect.top) / Magnification );
let id = "X"+ x + "Y" + y;
if( !MarubatsuTable[id] )
{
if( FirstStrike )
{
MarubatsuTable[id] = "○";
context.beginPath();
context.arc( (x+0.5)*Magnification, (y+0.5)*Magnification, Magnification/3 , 0, 2 * Math.PI, false ) ;
context.stroke();
}
else
{
MarubatsuTable[id] = "×";
context.beginPath();
context.moveTo((x+0.2)*Magnification, (y+0.2)*Magnification);
context.lineTo((x+0.8)*Magnification, (y+0.8)*Magnification);
context.moveTo((x+0.8)*Magnification, (y+0.2)*Magnification);
context.lineTo((x+0.2)*Magnification, (y+0.8)*Magnification);
context.stroke();
}
// 結果判定
const decisionTable =
[ {dicision:["X0Y0","X1Y0","X2Y0"],line:{x0:0,y0:0.5,x1:3,y1:0.5}},
{dicision:["X0Y1","X1Y1","X2Y1"],line:{x0:0,y0:1.5,x1:3,y1:1.5}},
{dicision:["X0Y2","X1Y2","X2Y2"],line:{x0:0,y0:2.5,x1:3,y1:2.5}},
{dicision:["X0Y0","X0Y1","X0Y2"],line:{x0:0.5,y0:0,x1:0.5,y1:3}},
{dicision:["X1Y0","X1Y1","X1Y2"],line:{x0:1.5,y0:0,x1:1.5,y1:3}},
{dicision:["X2Y0","X2Y1","X2Y2"],line:{x0:2.5,y0:0,x1:2.5,y1:3}},
{dicision:["X0Y0","X1Y1","X2Y2"],line:{x0:0,y0:0,x1:3,y1:3}},
{dicision:["X2Y0","X1Y1","X0Y2"],line:{x0:0,y0:3,x1:3,y1:0}} ];
decisionTable.forEach((a)=>
{
var temp = MarubatsuTable[a.dicision[0]] + MarubatsuTable[a.dicision[1]] + MarubatsuTable[a.dicision[2]];
if( temp == "○○○" || temp == "×××" )
{
context.beginPath();
context.moveTo( a.line.x0*Magnification, a.line.y0*Magnification);
context.lineTo( a.line.x1*Magnification, a.line.y1*Magnification);
context.stroke();
Finished = true;
}
if( Object.keys(MarubatsuTable).length == 9 )
{
Finished = true;
}
});
// 先攻後攻変更
FirstStrike = !FirstStrike;
}
}
function onLoad(){
canvas = document.getElementById('sampleCanvas');
context = canvas.getContext('2d');
if ( ! canvas || ! context ) {
return false;
}
canvas.style.width = Magnification * 3+"px";
canvas.style.height = Magnification * 3+"px";
canvas.width = Magnification * 3;
canvas.height = Magnification * 3;
drawFrame();
canvas.addEventListener('click', onClick, false);
}
onLoad();
</script>
<!-------------------------------->
<pre class="src"><!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="utf-8">
<script>
let canvas;
let context;
let Magnification = 100;
let Finished = false;
let FirstStrike=true;
let MarubatsuTable={};
function drawFrame()
{
// #を描画
context.beginPath();
context.moveTo(Magnification*0, Magnification*1);
context.lineTo(Magnification*3, Magnification*1);
context.moveTo(Magnification*0, Magnification*2);
context.lineTo(Magnification*3, Magnification*2);
context.moveTo(Magnification*1, Magnification*0);
context.lineTo(Magnification*1, Magnification*3);
context.moveTo(Magnification*2, Magnification*0);
context.lineTo(Magnification*2, Magnification*3);
context.stroke();
}
function onClick(e)
{
if( Finished )
{
// ゲームが終わっている場合はリセット
context.clearRect(0, 0, canvas.width, canvas.height);
drawFrame();
MarubatsuTable = {};
Finished = false;
FirstStrike = true;
return;
}
// クリックされたセルを検出
let rect = e.target.getBoundingClientRect();
let x = Math.floor( (e.clientX - rect.left) / Magnification );
let y = Math.floor( (e.clientY - rect.top) / Magnification );
let id = "X"+ x + "Y" + y;
if( !MarubatsuTable[id] )
{
if( FirstStrike )
{
MarubatsuTable[id] = "○";
context.beginPath();
context.arc( (x+0.5)*Magnification, (y+0.5)*Magnification, Magnification/3 , 0, 2 * Math.PI, false ) ;
context.stroke();
}
else
{
MarubatsuTable[id] = "×";
context.beginPath();
context.moveTo((x+0.2)*Magnification, (y+0.2)*Magnification);
context.lineTo((x+0.8)*Magnification, (y+0.8)*Magnification);
context.moveTo((x+0.8)*Magnification, (y+0.2)*Magnification);
context.lineTo((x+0.2)*Magnification, (y+0.8)*Magnification);
context.stroke();
}
// 結果判定
const decisionTable =
[ {dicision:["X0Y0","X1Y0","X2Y0"],line:{x0:0,y0:0.5,x1:3,y1:0.5}},
{dicision:["X0Y1","X1Y1","X2Y1"],line:{x0:0,y0:1.5,x1:3,y1:1.5}},
{dicision:["X0Y2","X1Y2","X2Y2"],line:{x0:0,y0:2.5,x1:3,y1:2.5}},
{dicision:["X0Y0","X0Y1","X0Y2"],line:{x0:0.5,y0:0,x1:0.5,y1:3}},
{dicision:["X1Y0","X1Y1","X1Y2"],line:{x0:1.5,y0:0,x1:1.5,y1:3}},
{dicision:["X2Y0","X2Y1","X2Y2"],line:{x0:2.5,y0:0,x1:2.5,y1:3}},
{dicision:["X0Y0","X1Y1","X2Y2"],line:{x0:0,y0:0,x1:3,y1:3}},
{dicision:["X2Y0","X1Y1","X0Y2"],line:{x0:0,y0:3,x1:3,y1:0}} ];
decisionTable.forEach((a)=>
{
var temp = MarubatsuTable[a.dicision[0]] + MarubatsuTable[a.dicision[1]] + MarubatsuTable[a.dicision[2]];
if( temp == "○○○" || temp == "×××" )
{
context.beginPath();
context.moveTo( a.line.x0*Magnification, a.line.y0*Magnification);
context.lineTo( a.line.x1*Magnification, a.line.y1*Magnification);
context.stroke();
Finished = true;
}
if( Object.keys(MarubatsuTable).length == 9 )
{
Finished = true;
}
});
// 先攻後攻変更
FirstStrike = !FirstStrike;
}
}
function onLoad(){
canvas = document.getElementById('sampleCanvas');
context = canvas.getContext('2d');
if ( ! canvas || ! context ) {
return false;
}
canvas.style.width = Magnification * 3+"px";
canvas.style.height = Magnification * 3+"px";
canvas.width = Magnification * 3;
canvas.height = Magnification * 3;
drawFrame();
canvas.addEventListener('click', onClick, false);
}
</script>
</head>
<body onload="onLoad();">
<canvas id="sampleCanvas"></canvas>
</body>
</html>
</pre>
<h2>おまけ:Canvas縛りがない場合はもっと簡単</h2>
<pre class="src"><!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="utf-8">
<script>
let FirstStrike=true;
let Finished = false;
let Count = 0;
function onClick(event){
// 勝敗決定後のクリックは結果クリア
if( Finished )
{
for (const td of event.currentTarget.querySelectorAll("td")) {
td.innerText = " ";
td.style.backgroundColor = "";
}
FirstStrike=true;
Finished = false;
Count = 0;
return;
}
// クリックされたセルに"○"/"×"を記録
if(event.target.tagName=="TD")
{
if( event.target.innerText==" " ){
event.target.innerText = FirstStrike?"○":"×";
FirstStrike =! FirstStrike;
Count++;
// 結果判定
const decisionTable =
[ ["00","01","02"],
["01","11","12"],
["02","21","22"],
["00","10","20"],
["01","11","21"],
["02","12","22"],
["00","11","22"],
["20","11","02"] ];
decisionTable.forEach((a)=>
{
var temp = document.getElementById(a[0]).innerText+document.getElementById(a[1]).innerText+document.getElementById(a[2]).innerText;
if( temp == "○○○" || temp == "×××" )
{
Finished = true;
document.getElementById(a[0]).style.backgroundColor = "lightblue";
document.getElementById(a[1]).style.backgroundColor = "lightblue";
document.getElementById(a[2]).style.backgroundColor = "lightblue";
}
});
if( Count >=9 )
{
Finished = true;
}
}
}
}
</script>
</head>
<body>
<table onclick="onClick(event);" border="1">
<tr><td id="00"> </td><td id="01"> </td><td id="02"> </td></tr>
<tr><td id="10"> </td><td id="11"> </td><td id="12"> </td></tr>
<tr><td id="20"> </td><td id="21"> </td><td id="22"> </td></tr>
</table>
</body>
</html></pre>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-50576755219059122682022-04-24T13:42:00.010+09:002024-01-17T22:40:28.643+09:00Googleフォトの「ロックされたフォルダ」の使い方と注意事項<p></p><div>※ロックされたフォルダもバックアップできる機能が追加されましたが検証が出来てないので、バックアップしない状態での仕様について書いてます。</div><ol style="text-align: left;"><li>「ロックされたフォルダ」の概要</li><ul><li>「ロックされたフォルダ」に入れるとロック解除しないと画像が閲覧できなくなります。他人に見られたくない画像などを保存する目的だと思います。</li><li>しかし、ゴミ箱を経由せずに消えるなどいろいろと危険な使用があるので大切な画像を「ロックされたフォルダ」に入れてはいけません。</li><li>大切ではないけど他人には見られたくない画像を保存するのが「ロックされたフォルダ」の用途です。</li></ul><li>「ロックされたフォルダ」の使い方</li><ul><li>入れる方法<br />Googleフォトアプリで写真を表示/写真を選択し、「︙」アイコンから「ロックされたフォルダに移動」を行う。</li><li>参照する方法<br />「ロックされたフォルダ」に入れる操作を行った端末のGoogleフォトアプリで 「ライブラリ」 > 「ユーティリティ」 > 「ロックされたフォルダ」 と選んでください。ロック解除はスマホのロック解除と同じ方法です。</li><li>出す方法<br />「ロックされたフォルダ」内の画像を選択して「移動」してください。</li></ul><li>ロックされたフォルダに入れるとどうなるか</li><ul><li>画像が端末にダウンロードされ、Googleフォトアプリの「ロックされたフォルダ」に保存される。</li><li>操作を行ったときに選択されていたアカウントのGoogleフォト( <a href="https://photos.google.com/login">https://photos.google.com/login</a> )から写真が削除される。</li></ul><li>ロックされたフォルダを使用するうえでの注意事項 </li><ul><li>「ロックされたフォルダ」内での削除操作はゴミ箱を経由しないので復元できない。</li><li>操作を行った端末のみに保存されるので端末故障/端末紛失/機種変更/端末初期化の際には画像がなくなる</li><li>操作を行ったときに選択されていたアカウントのGoogleフォト( <a href="https://photos.google.com/login">https://photos.google.com/login</a> )から写真が削除されるが、他のアカウントからは消えない、パートナー共有などで複数のアカウントに画像があるときはすべてのアカウントで「ロックされたフォルダ」に入れる必要がある。</li><li>他のアプリから参照できなくなる。</li><li>「ロックされたフォルダ」から出すと再度バックアップ対象になるので、2021/5/31以前にバックアップし容量無制限の対象だった画像も容量カウントの対象になる。</li><li>撮影日時が保存されていない画像形式(PNG形式で保存されたスクリーンショット画像)はロックされたフォルダに入れるとファイルタイムスタンプが更新されていつ撮影されたか分からなくなる。</li></ul><li>ロックされたフォルダの活用方法</li><ol><li>Pixel 5以前の端末など、節約画質で容量無制限の特典が利用できる端末で「ロックされたフォルダ」(バックアップしない設定)に入れた後に、節約画質でバックアップする設定にしてから「ロックされたフォルダ」から出すと特典が適用される。iPhoneなど対象外の端末からバックアップした画像を無制限の対象に変換できる。</li><li>AndroidのGoogleフォトアプリには画像を一括ダウンロードする方法が提供されていないが、「ロックされたフォルダ」には一括でダウンロードできる。「ロックされたフォルダ」に入れ、すぐに出すことで一括ダウンロードが可能になるが、、、再度バックアップが行われるので注意が必要</li></ol></ol><p></p>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com4tag:blogger.com,1999:blog-4133168287384904096.post-30575029904305389502022-04-24T10:30:00.006+09:002023-05-29T05:08:59.523+09:00AndroidのGoogleフォトアプリを再インストールする方法<p><br /> Googleフォトは基本的にクラウドにデータを保存しているため、Googleフォトアプリを再インストールしても問題ないと思いがちですが、以下のデータ消えるので注意が必要です。</p><p></p><ul style="text-align: left;"><li>アカウントにログインするための情報</li><li>バックアップと同期設定</li><li>ロックされたフォルダの画像</li></ul><p>Googleフォトアプリを再インストール手順を示します。流れとしては以下になります。<br /></p><ol style="text-align: left;"><li>アカウント確認</li><li>全アカウントへのログイン確認</li><li>Googleフォトアプリの設定確認</li><li>バックアップと同期オフ設定<br />(ロックされたフォルダのあったデータをバックアップされないようにする)</li><li>ロックされたフォルダから画像移動</li><li>アプリの削除</li><li>アプリの再インストール</li><li>ロックされたフォルダの復元</li><li>バックアップと同期やその他の設定の復元</li></ol><p></p><p>上記で操作できる人は移行は読まなくてもよいです。勘違いする人が多かったり、間違えてほしくない部分だけ画像を貼ってます。画像を貼ってほしい手順があればコメントください。</p><p></p><ol><li>アカウント確認<br />Googleフォトアプリの右上のアカウントアイコンをタップし、表示されたメニューのアカウントの右側をタップして登録しているアカウントを全てメモする<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcWXbg8fsZ113KAKSeFVTm7Z4Gz6F4S8ynBUp43ZryPqvYQ7kzv1aMbUc0VG4Dw9Al5B1g-aBj-rAf3EmnwBCohIFxvvslDIdFo8S7F8ITgJehv6lY-AKXRK5cHi7XhrC0Gn835UbagWzblyWF7v_7ID_40HqzHjaN2lDpx3iSr1n2KI034buQzCZ8/s1658/0D85A407-3F8E-46C7-985F-403DEB9852A3.jpeg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1658" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcWXbg8fsZ113KAKSeFVTm7Z4Gz6F4S8ynBUp43ZryPqvYQ7kzv1aMbUc0VG4Dw9Al5B1g-aBj-rAf3EmnwBCohIFxvvslDIdFo8S7F8ITgJehv6lY-AKXRK5cHi7XhrC0Gn835UbagWzblyWF7v_7ID_40HqzHjaN2lDpx3iSr1n2KI034buQzCZ8/w130-h200/0D85A407-3F8E-46C7-985F-403DEB9852A3.jpeg" width="130" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipc8xf9TXrgPgJW5w4pFr1TVSlTFjlV7alBXxYDi8sy7mpsWLtuoA46MXN7cewQ8xlrCNyzHB4yK-JszR1fK-x1meyvCFFTVKAlme5K4U_jTd_P6urnt0GEp1Mhmj5FfkQ0WvmOydt3joYasrXyP2Xw6KUDeInU_qK8vkeokj4g75Df5Jt1lMNXfiE/s1687/4A246509-E507-4A7B-BE3F-A474C4F7384D.jpeg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1687" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipc8xf9TXrgPgJW5w4pFr1TVSlTFjlV7alBXxYDi8sy7mpsWLtuoA46MXN7cewQ8xlrCNyzHB4yK-JszR1fK-x1meyvCFFTVKAlme5K4U_jTd_P6urnt0GEp1Mhmj5FfkQ0WvmOydt3joYasrXyP2Xw6KUDeInU_qK8vkeokj4g75Df5Jt1lMNXfiE/w128-h200/4A246509-E507-4A7B-BE3F-A474C4F7384D.jpeg" width="128" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJa_1Pai_lVPX3eBwiVZ9WZEPVpl8Qn9sPANvLdRKkEX2Dq80SLW3bpjauV1CHBDIxq5eVHbQQrKMDn_xcohm91yaxJKa4apjm8y7oKwu3bWxkXSha_JwFy0eXMIJq63ZgCS5y4n4-uW2SpOVblKX1__5a7JtbxIi9nASQ23oHWhp7e63dnp9cmbuw/s1724/EA4DCD09-8ABA-4BF8-BC00-35279EAC1743.jpeg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1724" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJa_1Pai_lVPX3eBwiVZ9WZEPVpl8Qn9sPANvLdRKkEX2Dq80SLW3bpjauV1CHBDIxq5eVHbQQrKMDn_xcohm91yaxJKa4apjm8y7oKwu3bWxkXSha_JwFy0eXMIJq63ZgCS5y4n4-uW2SpOVblKX1__5a7JtbxIi9nASQ23oHWhp7e63dnp9cmbuw/w125-h200/EA4DCD09-8ABA-4BF8-BC00-35279EAC1743.jpeg" width="125" /></a><br /><br /></li><li>全アカウントへのログイン確認<br />ChromeブラウザのシークレットモードでGoogleフォト( <a href="https://photos.google.com/login">https://photos.google.com/login</a> )にアクセスして上記でメモしたアカウントすべてでログイン操作を行い、以下のことを確認する。<br />・左上が「≡」アイコンである事(アプリに飛ばされていないことの確認)<br />・今までバックアップしていた画像が存在する事<br />・全てのアカウントにログインできる事を確認する<br /><div style="text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjxJiJcVp4y7n9GV0zi3YIQIthPLdpEWSfZ_Hju6MMMyfC5nCbiSBzjzScuqmZCPBDXgutT8IJ0C4bcJtr5qgxdut32vrREZnYpncAj9K8QuLeHpby11UPhuYIst4m8-RnN3xh7oV2Mo8XF_Kb3uZ4-l71zI7o3lSVFn_eh2A6GcdF2HYM_lptS6A96A/s1723/Screenshot_20220424-092052_3.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1723" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjxJiJcVp4y7n9GV0zi3YIQIthPLdpEWSfZ_Hju6MMMyfC5nCbiSBzjzScuqmZCPBDXgutT8IJ0C4bcJtr5qgxdut32vrREZnYpncAj9K8QuLeHpby11UPhuYIst4m8-RnN3xh7oV2Mo8XF_Kb3uZ4-l71zI7o3lSVFn_eh2A6GcdF2HYM_lptS6A96A/w126-h200/Screenshot_20220424-092052_3.jpg" width="126" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisrLjh4HkMTnNo05_Ip0-RmwDpFLh0YuTAo4F56gXJFWoCC1LAISq_CxCAH0jZeP34Ihm04v6Lo7C-Qxyl_AXzPXwC2bIkN3-OJ7QpR_Q9kQBee2t9HCAGsZWBXUQD9yED3G7NHP8TJhXUaxaM0-YToyYHpJ0EuzeShtYQCZwm0OlEBWZs2P8sAVJ6aw/s1559/Screenshot_20220424-092101_2.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1559" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisrLjh4HkMTnNo05_Ip0-RmwDpFLh0YuTAo4F56gXJFWoCC1LAISq_CxCAH0jZeP34Ihm04v6Lo7C-Qxyl_AXzPXwC2bIkN3-OJ7QpR_Q9kQBee2t9HCAGsZWBXUQD9yED3G7NHP8TJhXUaxaM0-YToyYHpJ0EuzeShtYQCZwm0OlEBWZs2P8sAVJ6aw/w139-h200/Screenshot_20220424-092101_2.jpg" width="139" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDZH7BEXYzsO3iy9cLwGynYnxUBY7Mwv1_iSfggnvRrC0agOHuLeoNAp05tGA0X2R0iEGRyqPLCpXXKrvB54d67Dzw6Ns1bhjQDtZSND7Le7EEO5HFr1prvUZqEed2HYH3pr9U200S6Yf9-ksJQ4DLeRokdV34yLCozQWFax_KbSHyR3KtzCSVM57i5w/s1498/Screenshot_20220424-093033_2.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1498" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDZH7BEXYzsO3iy9cLwGynYnxUBY7Mwv1_iSfggnvRrC0agOHuLeoNAp05tGA0X2R0iEGRyqPLCpXXKrvB54d67Dzw6Ns1bhjQDtZSND7Le7EEO5HFr1prvUZqEed2HYH3pr9U200S6Yf9-ksJQ4DLeRokdV34yLCozQWFax_KbSHyR3KtzCSVM57i5w/w144-h200/Screenshot_20220424-093033_2.jpg" width="144" /></a><br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYXFFZNZ7zvxYmA18OCLZwVR-yLcNpESAxYxokt3VruCy1Qe7Q8LReuVV7LxD7DmgMrjUIOGlYO43hTXN5Miw0hQJjmSBj0EY3vgL5FA3n3wbqvUMLpbqEt5prX78xzyxqiXNXyJNjKc8xLSWJtyZEcNW7qlCic80vHTckAdYno4Qe-rOSPwvXtMP7pw/s1509/Screenshot_20220424-092846_2.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1509" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYXFFZNZ7zvxYmA18OCLZwVR-yLcNpESAxYxokt3VruCy1Qe7Q8LReuVV7LxD7DmgMrjUIOGlYO43hTXN5Miw0hQJjmSBj0EY3vgL5FA3n3wbqvUMLpbqEt5prX78xzyxqiXNXyJNjKc8xLSWJtyZEcNW7qlCic80vHTckAdYno4Qe-rOSPwvXtMP7pw/w143-h200/Screenshot_20220424-092846_2.jpg" width="143" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSRdIZbAWMs6WAeUexf7OUZF6jBjxwcDlyfEQQzH22mism3_FLDfQikNZTcVxZD53n38CgzFtvzcHT83qZWxSPaWURWbylLGfF16cAYV3fUTZEqEV_fRQBsqmnyDf55273szBmo4Pq0Uwrn2IwUjmc0zzhNGANDMKNSuen5eZkVL3jMEjWnRTPcdB2BA/s1694/Screenshot_20220424-094700_2.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1694" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSRdIZbAWMs6WAeUexf7OUZF6jBjxwcDlyfEQQzH22mism3_FLDfQikNZTcVxZD53n38CgzFtvzcHT83qZWxSPaWURWbylLGfF16cAYV3fUTZEqEV_fRQBsqmnyDf55273szBmo4Pq0Uwrn2IwUjmc0zzhNGANDMKNSuen5eZkVL3jMEjWnRTPcdB2BA/w127-h200/Screenshot_20220424-094700_2.jpg" width="127" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ptBK0DXSo7r3gJkInpXa3yvraqSeAfHVwbwZ08k_mJf-svHhrsnQisZJtO5PMCMRcMlVi5tbE9smLZpIqpYPnVokLiefJr-wknCmWVjj0p2mQsZBZq7pe-c_kAm_HSAQphLF0YEAeIYlJLewvImRESU-iou5vyEV_fVhxCWIAW7jYFgMjp2ZnZh3bQ/s1641/Screenshot_20220424-094707_2.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1641" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-ptBK0DXSo7r3gJkInpXa3yvraqSeAfHVwbwZ08k_mJf-svHhrsnQisZJtO5PMCMRcMlVi5tbE9smLZpIqpYPnVokLiefJr-wknCmWVjj0p2mQsZBZq7pe-c_kAm_HSAQphLF0YEAeIYlJLewvImRESU-iou5vyEV_fVhxCWIAW7jYFgMjp2ZnZh3bQ/w132-h200/Screenshot_20220424-094707_2.jpg" width="132" /></a><br /><br /></div></li><li>Googleフォトアプリの設定確認<br />Googleフォトアプリの右上のアカウントアイコンをタップし、「フォトの設定」に行き、設定をメモする。<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcWXbg8fsZ113KAKSeFVTm7Z4Gz6F4S8ynBUp43ZryPqvYQ7kzv1aMbUc0VG4Dw9Al5B1g-aBj-rAf3EmnwBCohIFxvvslDIdFo8S7F8ITgJehv6lY-AKXRK5cHi7XhrC0Gn835UbagWzblyWF7v_7ID_40HqzHjaN2lDpx3iSr1n2KI034buQzCZ8/s1658/0D85A407-3F8E-46C7-985F-403DEB9852A3.jpeg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1658" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcWXbg8fsZ113KAKSeFVTm7Z4Gz6F4S8ynBUp43ZryPqvYQ7kzv1aMbUc0VG4Dw9Al5B1g-aBj-rAf3EmnwBCohIFxvvslDIdFo8S7F8ITgJehv6lY-AKXRK5cHi7XhrC0Gn835UbagWzblyWF7v_7ID_40HqzHjaN2lDpx3iSr1n2KI034buQzCZ8/w130-h200/0D85A407-3F8E-46C7-985F-403DEB9852A3.jpeg" width="130" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2TSBq0UmJKGcpD_iUNtAcoze-WBmR6kc-ivYXsnOOojJBkXCikcmj-D42EpZq4qBp8aZD8cHpZhUYjRXF5a1-ZNV3fgOdXwYz-yplzqgiD2AouESHuzN2Ca1PKpU5r0ldXObd3cN9lbf4JfoxKA9IHhHnWIAC5su-OgryM2gQdg4_r0CpB48vskkVsA/s1625/Screenshot_20220424-100947_2.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1625" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2TSBq0UmJKGcpD_iUNtAcoze-WBmR6kc-ivYXsnOOojJBkXCikcmj-D42EpZq4qBp8aZD8cHpZhUYjRXF5a1-ZNV3fgOdXwYz-yplzqgiD2AouESHuzN2Ca1PKpU5r0ldXObd3cN9lbf4JfoxKA9IHhHnWIAC5su-OgryM2gQdg4_r0CpB48vskkVsA/w133-h200/Screenshot_20220424-100947_2.jpg" width="133" /></a><br /><br /></li><li>バックアップ<strike>と同期</strike>オフ設定<br />「フォトの設定」 > 「バックアップ<strike>と同期</strike>」画面に行き、バックアップ<strike>と同期</strike>をオフにする。<br /><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2TSBq0UmJKGcpD_iUNtAcoze-WBmR6kc-ivYXsnOOojJBkXCikcmj-D42EpZq4qBp8aZD8cHpZhUYjRXF5a1-ZNV3fgOdXwYz-yplzqgiD2AouESHuzN2Ca1PKpU5r0ldXObd3cN9lbf4JfoxKA9IHhHnWIAC5su-OgryM2gQdg4_r0CpB48vskkVsA/s1625/Screenshot_20220424-100947_2.jpg" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="1625" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2TSBq0UmJKGcpD_iUNtAcoze-WBmR6kc-ivYXsnOOojJBkXCikcmj-D42EpZq4qBp8aZD8cHpZhUYjRXF5a1-ZNV3fgOdXwYz-yplzqgiD2AouESHuzN2Ca1PKpU5r0ldXObd3cN9lbf4JfoxKA9IHhHnWIAC5su-OgryM2gQdg4_r0CpB48vskkVsA/w133-h200/Screenshot_20220424-100947_2.jpg" width="133" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVYuc88DMINObMUlwXAEyAzOGyoIX2kHI6hVBEhG7jtXDHUY2KP_OKyX64fX1xFpPUTGIBGRvpdKzSZy4zdQtqZevVI-URyMBYus3ravoBzBHEgG-WPBVWvqTiRb56Lo31B-aUVelXe7ND_swi4maXtrPSwKhbbK39i4sqU77A-TpiTvUYYMAkxUtPQ/s1534/Screenshot_20220424-101328.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1534" data-original-width="1079" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjiVYuc88DMINObMUlwXAEyAzOGyoIX2kHI6hVBEhG7jtXDHUY2KP_OKyX64fX1xFpPUTGIBGRvpdKzSZy4zdQtqZevVI-URyMBYus3ravoBzBHEgG-WPBVWvqTiRb56Lo31B-aUVelXe7ND_swi4maXtrPSwKhbbK39i4sqU77A-TpiTvUYYMAkxUtPQ/w141-h200/Screenshot_20220424-101328.png" width="141" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg61_BlXkJBasYl7pL-jZi8H5agjGuImB3_g-0DCx175gGw_N58rvH09OO_BAAiQc1B7eZeeQOlgol-BnRydNPfzuAF19qRXDrz_yUyyqSRq96mGjR0KxF3Q9kSg7YmjI9W-T2WFEvz1RL6VpUnTmIpVSypH4c1ss4pF3MUT9DMGK7dsasMErKg4lNnkw/s1495/Screenshot_20220424-101051_2.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1495" data-original-width="1080" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg61_BlXkJBasYl7pL-jZi8H5agjGuImB3_g-0DCx175gGw_N58rvH09OO_BAAiQc1B7eZeeQOlgol-BnRydNPfzuAF19qRXDrz_yUyyqSRq96mGjR0KxF3Q9kSg7YmjI9W-T2WFEvz1RL6VpUnTmIpVSypH4c1ss4pF3MUT9DMGK7dsasMErKg4lNnkw/w144-h200/Screenshot_20220424-101051_2.jpg" width="144" /></a><br /><br /><br /></li><li>ロックされたフォルダから画像移動<br />「ライブラリ」 > 「ユーティリティ」 > 「ロックされたフォルダ」を開き、そこにある画像すべてを移動する。ここで「削除」を押すと復元できないので要注意。<br />どんな画像があったか覚えておく、写真の枚数が多い場合には撮影日時などをメモしておくとよい。<br /><br /></li><li>アプリの削除<br />Googleフォトアプリを削除(アンインストール)する。<br /><br /></li><li>アプリの再インストール<br />Play StoreアプリでGoogleフォトを検索してインストールを行う。インストールの途中でバックアップと同期を有効にする手順があった場合には有効にしないように注意する。<br /><br /></li><li>ロックされたフォルダの復元<br />フォトの中からロックされたフォルダに移動したい写真を選択して、ロックされたフォルダに移動する。<br /><br /></li><li>バックアップと同期やその他の設定の復元<br />アプリの設定をすべて元に戻す。<br /><br /></li></ol>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-9607189469354409162022-04-18T00:22:00.003+09:002022-04-18T00:22:40.993+09:00ネットワーク速度の確認方法<h2 style="text-align: left;">1. <a href="https://www.google.co.jp/">https://www.google.co.jp/</a>にアクセスする</h2><h2 style="text-align: left;">2. 「スピードテスト」を検索する</h2><h2 style="text-align: left;">3. 速度テストを実行</h2><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMvqY4AnaTjJrMziZ37U9DT_9OmxReAIUfT4O7Ij4p1cMzO1vYdeiKhtmBWlPo3uLL70h2OhIatfzrLvoqWR4gXsp6pUcOGZvVP0SXPxWU08rQKxURTSZEnBGxgeEALetegtigypEUuB0-QsyXyHMeas5xnfXXDsONo3u3nE8-Hj9cbO9IDvu83-IK/s2208/D4435FC3-4F93-4582-B982-0E584CE03B95.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMvqY4AnaTjJrMziZ37U9DT_9OmxReAIUfT4O7Ij4p1cMzO1vYdeiKhtmBWlPo3uLL70h2OhIatfzrLvoqWR4gXsp6pUcOGZvVP0SXPxWU08rQKxURTSZEnBGxgeEALetegtigypEUuB0-QsyXyHMeas5xnfXXDsONo3u3nE8-Hj9cbO9IDvu83-IK/s320/D4435FC3-4F93-4582-B982-0E584CE03B95.jpeg" width="180" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxLXIX6EJra5lnaB11iEMmXzet5APdqBl1g00SOhSXZLIBHqkv38zzxYFUP5xdnB7XIlMHuySeTkYy4JzgdbDa0JUOdIcWObyUNGNFjsl-v4zk3FT6OcKwR4qTSaYqxfrG3DtUYUSTHxWHCTejeTwy9oydWv-t9_9JBrjB6byjr8VzmrHZ1lLOgrbn/s2208/A9B1584E-F140-4F10-B5DA-2AF35CE40C8D.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxLXIX6EJra5lnaB11iEMmXzet5APdqBl1g00SOhSXZLIBHqkv38zzxYFUP5xdnB7XIlMHuySeTkYy4JzgdbDa0JUOdIcWObyUNGNFjsl-v4zk3FT6OcKwR4qTSaYqxfrG3DtUYUSTHxWHCTejeTwy9oydWv-t9_9JBrjB6byjr8VzmrHZ1lLOgrbn/s320/A9B1584E-F140-4F10-B5DA-2AF35CE40C8D.jpeg" width="180" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFjecPpha-zM_n0xnBED_HMsUiU_S8FxJ6l1X9YZhC7wM9aGK3h_aguRTfsogmb6pCytQihbfStL3xlRENAj_0ihSeuPoQeRIUH3ZRbkf4adhmPcjEEtaimVpcajVUeSy54s1lGKRnxtvvFusfZTl2YOTI3r7-HwHOONijzj_CBCqN4I18VORbZehp/s2208/5984A93F-3007-45F4-9EA1-3F06B97892F3.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="2208" data-original-width="1242" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFjecPpha-zM_n0xnBED_HMsUiU_S8FxJ6l1X9YZhC7wM9aGK3h_aguRTfsogmb6pCytQihbfStL3xlRENAj_0ihSeuPoQeRIUH3ZRbkf4adhmPcjEEtaimVpcajVUeSy54s1lGKRnxtvvFusfZTl2YOTI3r7-HwHOONijzj_CBCqN4I18VORbZehp/s320/5984A93F-3007-45F4-9EA1-3F06B97892F3.jpeg" width="180" /></a><br /><br /></div><br /><div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-14912597400781214542022-03-21T15:52:00.017+09:002022-04-29T17:20:15.724+09:00G Suite アカウントを無料で継続利用する方法<h1 style="text-align: left;">Google Workspaceに課金せずデータを引き継ぐ</h1><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheswjIqgmZfnGbsxoiLBtE7BBOzhZTrY4YkWE_JqqTcmOFv0QE7sKnfUCLOfZFm4IwzDLyDitz3Rc_MtEWTdf4HOh0-v3by53gH0YD5_Cq6ISu1z9-_aslWksXQnkHgwk8DKTz6-E_Col6FCerVlDzcd3qgyyBOyRljc2WVaDphnJgH2RL0HN8e-heKw/s957/Google%20Cloud%20Identity%20Free.PNG" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="332" data-original-width="957" height="111" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheswjIqgmZfnGbsxoiLBtE7BBOzhZTrY4YkWE_JqqTcmOFv0QE7sKnfUCLOfZFm4IwzDLyDitz3Rc_MtEWTdf4HOh0-v3by53gH0YD5_Cq6ISu1z9-_aslWksXQnkHgwk8DKTz6-E_Col6FCerVlDzcd3qgyyBOyRljc2WVaDphnJgH2RL0HN8e-heKw/s320/Google%20Cloud%20Identity%20Free.PNG" width="320" /></a></div><br /><div>G Suite Legacy(無料版Google Workspace)から有料Google Workspaceに移行せずにアカウントを維持する方法をサポートに教えてもらったので共有します。</div><div>メールは他のサーバーに移行すれば良いので、YouTube、Google フォト、Google Play、有料コンテンツが引き続き利用できるのは非常に大きいが、ヘルプにより記載内容が異なっているので問い合わせてみました。</div><div>問い合わせた結果から実際に試してみました。(2022/3/23)</div><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><div style="text-align: left;"><b style="background-color: #fff2cc;"><span style="font-size: large;">他の方法も用意されているようなのでもう少し様子見がよさそうです。:2022/4/29追記</span></b></div></blockquote><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3utqnhjQLy1Zgi-Ycs5VBGJ0NxvjsrFlcSJbgSa7131OSALKECxAp1IpYCQhnLiXNTwd5kTFcJxhAeOH4mR_aSuiBfyd6dDzf3styiPS9hgpdjBvIogQC9DYU28Z00iMVBLyZ9jCgRDsE_l70mML-3tliic9ArsRGwhpQB4VIZUHLfdX4-eKTcBlIBg/s505/GSuiteLegacy%E3%81%8B%E3%82%89%E3%81%AE%E7%84%A1%E6%96%99%E3%83%97%E3%83%A9%E3%83%B3%E7%A7%BB%E8%A1%8C.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><b><img border="0" data-original-height="185" data-original-width="505" height="146" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3utqnhjQLy1Zgi-Ycs5VBGJ0NxvjsrFlcSJbgSa7131OSALKECxAp1IpYCQhnLiXNTwd5kTFcJxhAeOH4mR_aSuiBfyd6dDzf3styiPS9hgpdjBvIogQC9DYU28Z00iMVBLyZ9jCgRDsE_l70mML-3tliic9ArsRGwhpQB4VIZUHLfdX4-eKTcBlIBg/w400-h146/GSuiteLegacy%E3%81%8B%E3%82%89%E3%81%AE%E7%84%A1%E6%96%99%E3%83%97%E3%83%A9%E3%83%B3%E7%A7%BB%E8%A1%8C.PNG" width="400" /></b></a><br /><br /></div></div><div><div><h2 style="text-align: left;">背景</h2>まず公式ヘルプ間の内容からおさらいです。
「<a href="https://support.google.com/a/answer/60217">従来の無償版 G Suite からのアップグレード</a>」によると2022/5以降に自動で有料のGoogle Workspaceに移行し、2022/7/1までは無料で、それ以降は有料になります。<br />
ただし、有料に移行したくなければGoogle Workspace のコアサービス(Gmail、カレンダー、Meet など)が利用できない<b><span>無料アカウントを引き続き利用できる</span></b>と書かれています。</div><div><br /><h2 style="text-align: left;">問い合わせた内容</h2>
有料に移行せずに無料のままその他の Google サービス(YouTube、Google フォト、Google Play など)や、有料コンテンツ(YouTube や Play ストアでの購入など)を引き続き利用する方法お問い合わせてみました。<br /></div><div><br /></div><div><h2 style="text-align: left;">回答してもらった内容</h2><span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;">・「有償版 Google Workspace のお支払い設定を未実施」であったとしても</span><span style="font-family: Arial;"><span style="font-size: 14.6667px; white-space: pre-wrap;">YouTube、Google フォト、Google Play 、Google ドライブ、ドキュメント、スプレッドシート、スライド、Keep、Meetは継続利用可能。(その他のサービスに関しての質問はあきらめました、知りたいサービスがある場合には有料サービスに契約したうえで、サポートに問い合わせてください。)</span></span></div><div><span style="font-family: Arial;"><span style="font-size: 14.6667px; white-space: pre-wrap;"><br /></span></span></div><div><span style="font-family: Arial;"><span style="font-size: 14.6667px; white-space: pre-wrap;">・ただし、</span></span><span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;">Google Workspace の支払い設定が未実施の状態だと放置アカウントとみなされて削除される可能性があるので</span>「Cloud Identity Free エディション」の追加をお勧めされました。</div><div><br /></div><div><span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;">・さらに、Google Workspace支払い</span><span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;">設定が未実施の状態だと管理コンソールで毎回支払い設定を促されるので、</span>「Cloud Identity Free エディション」を追加をするために<span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;">一旦Google Workspace のサブスクリプションを契約したうえで、</span>「Cloud Identity Free エディション」を追加後に<span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;">サブスクリプションを解約することを推奨する、とのことです。</span></div><div><span style="background-color: white; font-family: Arial; font-size: 14.6667px; white-space: pre-wrap;"><br /></span></div><div>・Cloud Identity については「<a href="https://support.google.com/cloudidentity/answer/7319251?hl=ja" target="_blank">Cloud Identity とは</a>」に書いてある。</div><div><br /></div><div>・2022/3/2時点で問い合わせ完了</div><div><br /><h2 style="text-align: left;">アカウントを削除されずにアカウントを使用し続ける方法</h2><div>Cloud Identity Freeエディションを追加するためには一度Google Workspaceの有料サブスクリプションにアップグレードする必要があります。Cloud Identity Freeエディションを追加後にGoogle Workspace サブスクリプションをキャンセルします。</div><div><div><h4>1.Google Workspace の有料サブスクリプションへのアップグレード手順</h4>管理コンソール > お支払い > その他のサービスを利用する > 左側 Google Workspace Business Starterの切り替えるをクリック > 開始 > フレキシブルプランを選択してご購入手続きをクリック</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjPn3c-J2MgQY_kqHjQbvPB15VpmBxCmbYd3cLbgpvTViLN_myQsIEN4j0b42OUorPxW0r2qRnAEQZS9gMRAjSgJaR4ypHigO7JHEFgZvYuzS1Q7hogoEJRb9iW6JZHKbGzzvF3VbcfhQtfllg5c5PFrX8b2u9sN7tkTyvANh6H7i0X3iRKwvwJNh1hBw=s925" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="925" data-original-width="803" height="200" src="https://blogger.googleusercontent.com/img/a/AVvXsEjPn3c-J2MgQY_kqHjQbvPB15VpmBxCmbYd3cLbgpvTViLN_myQsIEN4j0b42OUorPxW0r2qRnAEQZS9gMRAjSgJaR4ypHigO7JHEFgZvYuzS1Q7hogoEJRb9iW6JZHKbGzzvF3VbcfhQtfllg5c5PFrX8b2u9sN7tkTyvANh6H7i0X3iRKwvwJNh1hBw=w174-h200" width="174" /></a></div><br /><div><br /></div><h4>2.Cloud Identity Free エディションの追加手順</h4>管理コンソール > お支払い > その他のサービスを利用する > 左側 Cloud Identity クリック > Cloud Identity Free を開始</div><h4 style="text-align: left;">3.Google Workspace サブスクリプションのキャンセル手順</h4>
管理コンソール > お支払い > サブスクリプションを管理 > サブスクリプションをキャンセル</div><div><br /></div><div><h2 style="text-align: left;">
使える機能、使えなくなる機能</h2>
使えなくなるのはコアサービスです、コアサービスに関しては「<a href="https://workspace.google.com/intl/ja/terms/user_features.html" target="_blank">Google Workspace 利用規約</a>」を見て下さい。しかし、「<a href="https://support.google.com/a/answer/60217">従来の無償版 G Suite からのアップグレード</a>」や「<a href="https://support.google.com/cloudidentity/answer/7319251?hl=ja" target="_blank">Cloud Identity とは</a>」の記載内容を見る限りコアサービス全てが使えなくなるんけでは無さそうですし、ヘルプにより記載内容も異なるのでもう少し調査しました。</div><div><br /></div><div><h3 style="text-align: left;">Cloud Identity Free Editionで使えない機能</h3><div>実際に使用できないことを確認したサービス。</div><ul style="text-align: left;"><li>Gmail</li><li>カレンダー</li><li>Google Meet(会議開催できない):2022/4/29追記</li><li>Google Chat</li><li>Currents</li><li>Google Jamboard</li><li>Google ToDo リスト</li><li>Workspace アドオン</li><li>Google Voice</li></ul></div><div><h3 style="text-align: left;">Cloud Identity Free Editionで使える機能</h3><div>Google Adminコンソールで有効/無効設定が可能なサービスおよび動作確認を行ったサービス。(*を付けた行は実際に使えることを確認した項目)<br />使えても機能制限がある可能性もあるようですので、例えばMeetは使えると回答をもらい、実際に会議にも参加できましたが、参加専用になるようです。:2022/4/29追記</div><ul style="text-align: left;"><li>Googleサイト*</li><li>Keep*</li><li>ドライブとドキュメント*</li><ul><li>ドキュメント*</li><li>スプレッドシート*</li><li>スライド*</li><li>Forms*</li></ul><li>ビジネス向けGoogleグループ*</li><li>Blogger</li><li>Chrome Web Store*</li><li>Colab*</li><li>FeedBurner</li><li>Google AdSense</li><li>Google Arts & Culture</li><li>Google Bookmarks</li><li>Google Chrome 同期</li><li>Google Cloud Platform</li><li>Google Developers</li><li>Google Domains</li><li>Google Earth*</li><li>Google Fi</li><li>Google Meet* (会議への参加のみ可能):2022/4/29追記</li><li>Google My Maps</li><li>Google Pay</li><li>Google Play</li><li>Google Play Console</li><li>Google Play ブックスパートナーセンター</li><li>Google Public Data</li><li>Google Search Console</li><li>Google Translator Toolkit</li><li>Google Trips</li><li>Google Voice</li><li>Google アドマネージャー</li><li>Google アナリティクス</li><li>Google アラート</li><li>Google カスタム検索</li><li>Google クラウドプリント</li><li>Google グループ</li><li>Google コンタクト</li><li>Google データエクスポート</li><li>Google データポータル</li><li>Google ニュース*</li><li>Google フォト*(データが引き継がれることを確認しました)</li><li>Google ブックス</li><li>Google マイビジネス</li><li>Google マップ*</li><li>Google 広告</li><li>Google 翻訳</li><li>Location History</li><li>Managed Google Play</li><li>Material Gallary</li><li>Merchant Center</li><li>Partner Dash</li><li>Pinpoint</li><li>Scholar プロフィール</li><li>Tour Creator</li><li>YouTube</li><li>ウェブとアプリのアクティビティ</li><li>キャンペーンマネージャー</li><li>スタジオ</li><li>応用デジタルスキル</li><li>検索とアシスタント</li><li>検索高校360</li><li>個人用ストレージ</li><li>Cloud Identity サービス</li><li>Google CloudでCloud Identity アカウントを利用可能</li><li>ChromeでCloud Identity アカウントを利用可能</li><li>Android Enterprise Upgrade</li><li>Androidの管理</li><li>数多くのサードパーティ製アプリケーション</li></ul><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgZC-RfTxtYMZSJJumtb9MdBQe43dTknAYoQrON8PDoqkMONu7hL-nLY0AnXLwualQzBlPuacP-BST7Zor0l3MrifI_zW_IYf8Jsu16vKSrCPtYIBa8h8iicOw1IDCY7AIgeE052FcNFqRbC4NELCgo_JG7IWy153J0uRlojlP21HUO4M28Q6hyOtj8Iw=s719" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="719" height="136" src="https://blogger.googleusercontent.com/img/a/AVvXsEgZC-RfTxtYMZSJJumtb9MdBQe43dTknAYoQrON8PDoqkMONu7hL-nLY0AnXLwualQzBlPuacP-BST7Zor0l3MrifI_zW_IYf8Jsu16vKSrCPtYIBa8h8iicOw1IDCY7AIgeE052FcNFqRbC4NELCgo_JG7IWy153J0uRlojlP21HUO4M28Q6hyOtj8Iw=w200-h136" width="200" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhG3ykXmmmVEHXBgNyuJgIV_KxcYSKI4EKg9S396l_qesHy3tHnQ0hOgZmnQqbh6iAg4v5KH2YHUb0T3NNBSl4sbDl_q4F4F2I7JB6Hf2Ds53k5qc9W53QEihWHMcUi_adt6yOqoUq40NGGR_Z60eN33dO6P_PClMNbxhIVPxLjuAJcGvKo7LY1zA5Rxw=s721" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="625" data-original-width="721" height="173" src="https://blogger.googleusercontent.com/img/a/AVvXsEhG3ykXmmmVEHXBgNyuJgIV_KxcYSKI4EKg9S396l_qesHy3tHnQ0hOgZmnQqbh6iAg4v5KH2YHUb0T3NNBSl4sbDl_q4F4F2I7JB6Hf2Ds53k5qc9W53QEihWHMcUi_adt6yOqoUq40NGGR_Z60eN33dO6P_PClMNbxhIVPxLjuAJcGvKo7LY1zA5Rxw=w200-h173" width="200" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEitS70yQ7QE5d4P26DovRgFLc49P_cDZOdrzh5eEN-nRYCqmkErLxcHkECav3tAhRcX9H19gsbEXMbbBD3d715PTyMoyBe9EXT6xfBLpJPKGetfzLSce3JNtRHOIsSRK_T0grKAupksOYoX7XslQU9gl3Han3xTUqpGn2Qju52r8wfaHj6iVyCWe1_E8w=s756" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="378" data-original-width="756" height="100" src="https://blogger.googleusercontent.com/img/a/AVvXsEitS70yQ7QE5d4P26DovRgFLc49P_cDZOdrzh5eEN-nRYCqmkErLxcHkECav3tAhRcX9H19gsbEXMbbBD3d715PTyMoyBe9EXT6xfBLpJPKGetfzLSce3JNtRHOIsSRK_T0grKAupksOYoX7XslQU9gl3Han3xTUqpGn2Qju52r8wfaHj6iVyCWe1_E8w=w200-h100" width="200" /></a></div></div><br /><div><br /></div></div><h3 style="text-align: left;">ヘルプの記載から使えるか不明な機能</h3><div><ul style="text-align: left;"><li>Currents</li><li>Google Cloud Search</li><li>Google Vault</li><li>Google Workspace Assured Controls</li><li>検索およびインテリジェンスの機能</li></ul><div><br /></div></div><h2 style="text-align: left;">無償で使用し続けるお勧めの手順</h2></div><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><div><div style="text-align: left;"><span style="background-color: #fff2cc;"><span style="font-size: large;">他の方法も用意されているようなのでもう少し様子見がよさそうです。:2022/4/29追記</span></span></div></div></blockquote><div><div><b><br /></b><ol style="text-align: left;"><li>G Suite経由でGoDaddyで購入したドメインを使用している場合には念のため他のレジストラに管理を移管する。(必須かどうか不明だが、メールサーバー移管と合わせて移管先レジストラを考えた方が良い。)</li><li>メールを別サーバーに移行する。</li><li>@gmail.com アドレスを取得し、2のメールを転送する、2のSMTPサーバー経由でメールを送れる様に設定する。(移行先サーバーのメールボックス容量が潤沢であれば不要)</li><li>無料期間中(~2022/6/30)にGoogle Workspace <b>Business </b>Xxxx の<b>フレキシブルプラン</b>にアップグレードする。(Enterpriseを選んだり年間プランを選ぶと有料になるので注意が必要)。</li><li>Cloud Identity Freeエディションを追加する。</li><li>Google Workspace 有料サブスクリプションをキャンセルする。</li></ol><h4 style="text-align: left;">注意事項:</h4></div></div><div><ul style="text-align: left;"><li>カレンダーは使用できないので@gmail.comで使用する</li><li>カレンダーに追加されているイベントを削除できなくなるという情報を得たので、事前に削除しておくことをお勧めします。:2022/4/29追記</li><li>Meetは参加専用になるようです。その他の機能も「使える」けど制限がある可能性がありそうです。:2022/4/29追記</li></ul></div>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-58077780550770384842022-03-05T20:14:00.005+09:002022-03-05T20:14:57.286+09:00GoogleのLens機能で読み取った文字列をパソコンにコピーする<h1 style="text-align: left;">手書きの文字列をパソコンに取り込む方法</h1><p>今回は以下のような手書き文字を認識した結果をパソコンに取り込む方法を説明します。</p><p>普通に書いたら完璧に認識されて面白くなかったので、認識しない程度の汚い字を頑張って書いてみた。「レンズのテスト 手書き文字認識」と書いたつもりです。</p><p><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgQE6cHg4QWBuV8BfEqAiBkHSPReh1t8En2Bw4c7NAANxYllW_B1UnRhHmcWGDOFaE_pzr_L5QjlAuhTeVlSETncHP7w-2W4lFO6KSgiLgprE-NCQeqkORO29PFTb0Wo99EKC3GSbMpC7cgsBjZ3Chm_klVDU2Avp1FB5OzsM_I7u8cKLpOoZZeBEMV9g=s4032" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="4032" data-original-width="3024" height="320" src="https://blogger.googleusercontent.com/img/a/AVvXsEgQE6cHg4QWBuV8BfEqAiBkHSPReh1t8En2Bw4c7NAANxYllW_B1UnRhHmcWGDOFaE_pzr_L5QjlAuhTeVlSETncHP7w-2W4lFO6KSgiLgprE-NCQeqkORO29PFTb0Wo99EKC3GSbMpC7cgsBjZ3Chm_klVDU2Avp1FB5OzsM_I7u8cKLpOoZZeBEMV9g=s320" width="240" /></a></p><h3 style="text-align: left;">認識した文字をパソコンに取り込む方法</h3><div>今回は2つの方法を説明します。</div><p></p><ol style="text-align: left;"><li>写真を保存してパソコンのGoogleフォトで文字を認識する方法</li><li>スマホのGoogle Lensアプリを使用してパソコンに取り込む</li></ol><p></p><p>1の方が手順が簡単ですが、画像が容量を圧迫するし、うまく認識せずに再撮影が必要になり無駄な画像が増えるのでお勧めしない。</p><p>順番に説明します。</p><p></p><h2 style="text-align: left;">1.写真を保存してパソコンのGoogleフォトで文字を認識する方法</h2><ol style="text-align: left;"><li>手書き文字をスマホのカメラで撮影する</li><li>Googleフォトアプリでバックアップする</li><li>パソコンのWEBブラウザ(ChromeブラウザやEdgeブラウザなど)で<a href="https://photos.google.com" target="_blank">Googleフォト( https://photos.google.com )</a>にアクセスしてその写真を開く</li><li>「画像からテキストをコピー」を行う<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjjFwdLp0N5MLBD7MN73a7V3rxiHeWuNrBk16x1nkj6tKeO6CfuXiLthdye6_acqnJbL2KJQgRrQ3MWfKct5jo1RsTIIomLyOri0_ZN4bJe0-HKXGwvl6UXw6XmB3UuQ_jLVvrBvypK3i0K8YVkW_FKdb-NZgp3Gi5AkNuJ5j2eU0wWgxxcQE89qerA2Q=s983" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="693" data-original-width="983" height="226" src="https://blogger.googleusercontent.com/img/a/AVvXsEjjFwdLp0N5MLBD7MN73a7V3rxiHeWuNrBk16x1nkj6tKeO6CfuXiLthdye6_acqnJbL2KJQgRrQ3MWfKct5jo1RsTIIomLyOri0_ZN4bJe0-HKXGwvl6UXw6XmB3UuQ_jLVvrBvypK3i0K8YVkW_FKdb-NZgp3Gi5AkNuJ5j2eU0wWgxxcQE89qerA2Q=s320" width="320" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh7JhUKkp7eAexcatIvEp40pptv8ATMt4ygA0PZlOq08bxl0ekKaTi3GZcQqxvUydQUJp-pReFCMWePu9egW7D4BXTnJDx5TtAihWVoYXjLA3-j83SSNaQHDOEge2EJkoFzBg5DXeSDXTRsdtIBMMDR9KhREQtEoDKFsxpcSTA70EzgrkPpen4PUv6Fqw=s983" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="693" data-original-width="983" height="226" src="https://blogger.googleusercontent.com/img/a/AVvXsEh7JhUKkp7eAexcatIvEp40pptv8ATMt4ygA0PZlOq08bxl0ekKaTi3GZcQqxvUydQUJp-pReFCMWePu9egW7D4BXTnJDx5TtAihWVoYXjLA3-j83SSNaQHDOEge2EJkoFzBg5DXeSDXTRsdtIBMMDR9KhREQtEoDKFsxpcSTA70EzgrkPpen4PUv6Fqw=s320" width="320" /></a><br /><br /></li></ol><h2 style="text-align: left;">2.スマホのGoogle Lensアプリを使用してパソコンに取り込む</h2><ol style="text-align: left;"><li>パソコンにChromeブラウザをインストールしてアカウントと同期する<br />同期するアカウントは スマホの設定 > デバイス情報 > Googleアカウント で確認する<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjoSgT7id6kBv45oED7Qlx9-NvefqB01XyITN1AbXxgT-rJlY4oaNDp87udW_CQUYpLy1Azwn1uaRHS_5r1iJVQ5UX3xH_fQh6WLj6GDusUHPNjC7hj7SEueRUL7bBHWCF7tptZE_8v_SoyAsthpIWmcZX_VC1eZjiH5vD57LRM9zbfgCk3qoxxqgLyvw=s797" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="483" data-original-width="797" height="194" src="https://blogger.googleusercontent.com/img/a/AVvXsEjoSgT7id6kBv45oED7Qlx9-NvefqB01XyITN1AbXxgT-rJlY4oaNDp87udW_CQUYpLy1Azwn1uaRHS_5r1iJVQ5UX3xH_fQh6WLj6GDusUHPNjC7hj7SEueRUL7bBHWCF7tptZE_8v_SoyAsthpIWmcZX_VC1eZjiH5vD57LRM9zbfgCk3qoxxqgLyvw=s320" width="320" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEigP_6U1j2pALs7EKeIcKENuNco66uw1NOxdi4AzUHL-WrgLipBo5evHA8BW3AJsW_ZTNMwXl7FhsNScYgzAdz6LZzE6u9j9Nga7TWP1GjJVvzqHPTs4xbJOxogdF__yh8_RH9ZyG52gAOPq_CMD1Q5-E4gOOexKUjjV2HdjNo7RgiKM4Omn3KKovABJg=s797" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="377" data-original-width="797" height="151" src="https://blogger.googleusercontent.com/img/a/AVvXsEigP_6U1j2pALs7EKeIcKENuNco66uw1NOxdi4AzUHL-WrgLipBo5evHA8BW3AJsW_ZTNMwXl7FhsNScYgzAdz6LZzE6u9j9Nga7TWP1GjJVvzqHPTs4xbJOxogdF__yh8_RH9ZyG52gAOPq_CMD1Q5-E4gOOexKUjjV2HdjNo7RgiKM4Omn3KKovABJg=s320" width="320" /></a><br /><br /></li><li>スマホにGoogle Lensアプリをインストールする</li><li>Google Lensアプリで画面下の「文字」を選択して、手書き文字を読み取る。読み取れた内容を選択&確認したら「パソコンにコピー」を行い、コピー先のパソコンを選択する<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgcpkVR11i6BtnoApx7shIhLu4pNm0vA0KwC7ZTPXGvdKgNDeVJI7hjCjR8TJJ7HbilTZlu0Z4VXwewlSvVL7Iks5tOq9mi0adVm8v5yLs0cgLb7A3-WGcZAEh911ItYsvCf59ZCgqLlkjFjNK8FSJM1BWV9bTnRw08gXG6c9vlh1IEnqLvLUpG2xpy5A=s2340" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="2340" data-original-width="1080" height="320" src="https://blogger.googleusercontent.com/img/a/AVvXsEgcpkVR11i6BtnoApx7shIhLu4pNm0vA0KwC7ZTPXGvdKgNDeVJI7hjCjR8TJJ7HbilTZlu0Z4VXwewlSvVL7Iks5tOq9mi0adVm8v5yLs0cgLb7A3-WGcZAEh911ItYsvCf59ZCgqLlkjFjNK8FSJM1BWV9bTnRw08gXG6c9vlh1IEnqLvLUpG2xpy5A=s320" width="148" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhviwO7EREB__8uHr-wiELJ7IfkFGKCLHXSzbKLfx97IqETOqGKUlJM3ujC06GXBYsgpmxUS2NKxSzkeTDl8MjXW8OTVV1-bVS9z_hyYWOAhjdG3uIJ4J1hSDyN9aBxeqO_gSORzTyZmDMmaAD3GP7ME8Cy3Wcwhkho3nT1CegCsHYpj49s7YK7aTnNcw=s2340" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="2340" data-original-width="1080" height="320" src="https://blogger.googleusercontent.com/img/a/AVvXsEhviwO7EREB__8uHr-wiELJ7IfkFGKCLHXSzbKLfx97IqETOqGKUlJM3ujC06GXBYsgpmxUS2NKxSzkeTDl8MjXW8OTVV1-bVS9z_hyYWOAhjdG3uIJ4J1hSDyN9aBxeqO_gSORzTyZmDMmaAD3GP7ME8Cy3Wcwhkho3nT1CegCsHYpj49s7YK7aTnNcw=s320" width="148" /></a><br /><br /></li><li>パソコンに通知が来たらパソコンのクリップボードに文字列がコピーされている<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEimJh8BsUqnHEih1YHRlMEE7Q8VA8TSi3p77MUx136YJq9YSjeoZQ7tCKRX5p1_lIcVaM3L5k1-e87BlHUGu1Ou0NwEy6cwEXMudr6Z1YIkKN0C2NmxQUwQ4KSSk2RIKQKGo9pjoYVCuWWqKr56heO9skSJvK6RWwGcAkA49mGCeipODyEkw7rGHqAbjA=s368" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="114" data-original-width="368" height="99" src="https://blogger.googleusercontent.com/img/a/AVvXsEimJh8BsUqnHEih1YHRlMEE7Q8VA8TSi3p77MUx136YJq9YSjeoZQ7tCKRX5p1_lIcVaM3L5k1-e87BlHUGu1Ou0NwEy6cwEXMudr6Z1YIkKN0C2NmxQUwQ4KSSk2RIKQKGo9pjoYVCuWWqKr56heO9skSJvK6RWwGcAkA49mGCeipODyEkw7rGHqAbjA=s320" width="320" /></a></li></ol><div><br /></div><br /><p></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p><p><br /></p>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-65101120910299194282022-02-26T10:40:00.006+09:002022-02-28T00:30:01.180+09:00GoogleDriveで共有されたデータをマイドライブにコピーする<a href="https://blog.hikozaru.com/2022/02/gsuite-legacy.html?m=1" target="_blank">G Suite無料のアカウントを無料で使い続ける方法</a>を知らない時にドライブのデータを頑張って移動するために作ったスクリプトを紹介します。<div>オーナー権限を変更するスクリプトもあったのですが、G Suite(Google Workspace)の制約で組織外のユーザーに権限移行ができないため、今回はフォルダ階層を維持したままコピーするスクリプトを作成しましたり</div><div><br /></div><div><div>アカウントを廃止するなどの目的でGoogleDriveで共有されたフォルダを自分のアカウントにコピーするスクリプトです。ご利用は自己責任で、、、<pre class="src">var me;
function CopyFolders() {
var url = "https://drive.google.com/drive/folders/<b>6dpqdZ1ESK<< ここはコピー元のフォルダURL >>yPoQBdhwEOP</b>";
var idAndResoucekey = url.replace(/.*\//g,"").split("?");
var id = idAndResoucekey[0];
var resoucekey = null;
me = Session.getActiveUser();
if( idAndResoucekey.length == 2 )
{
resoucekey = idAndResoucekey[1].replace(/.*=/,"");
}
var srcFolder = DriveApp.getFolderByIdAndResourceKey(id,resoucekey);
var dstFolder = getFolder( null, '共有フォルダからのコピー', false );
CopyFolder( srcFolder, dstFolder );
}
function CopyFolder(src,dst){
var folders = src.getFolders();
var files = src.getFiles();
while( folders.hasNext() )
{
var folder = folders.next();
CopyFolder( folder, getFolder( dst, folder.getName() ) );
if( src.getFiles().hasNext() )
{
Logger.log("削除できないファイルが残ってる?");
}else{
folder.removeEditor(me);
}
}
while( files.hasNext() )
{
var file = files.next();
try
{
file.makeCopy(file.getName(),dst);
file.removeEditor(me);
}
catch(e)
{
Logger.log(file.getName()+" 削除失敗");
}
}
}
/**
* 指定されたフォルダ取得する、フォルダがないときは新規に作成する。
*
* @param {Folder} parent 基準フォルダ、null指定時はルートフォルダ
* @param {string|Array of strings} name 取得・生成するフォルダ名
* string 指定時はnameを取得。生成する
* Array of strings 指定時は多階層フォルダを一括作成
* @param {bool} noCreate 作成は行わず既存のフォルダを取得するときにtrue
* 省略可能、省略時はfalseとして動作
* @return {Folder|undefined} 取得・生成したフォルダ
*/
function getFolder( parent, name, noCreate ) {
// 親フォルダが指定されなかった場合はルートフォルダを取得する。
if ( parent == null ){
var folder = DriveApp.getRootFolder();
}else{
var folder = parent;
}
// フォルダ名に配列が指定されていない場合は配列にする。
if( !Array.isArray( name ) ){
name = [name];
}
// noCreateが指定されていない場合はfalseにする。
if ( noCreate !== true ){
noCreate = false;
}
while( name.length > 0 ){
var newFolder = name.shift();
var childs = folder.getFoldersByName( newFolder );
if( childs.hasNext() ){
// フォルダが見つかった場合は最初のフォルダを採用
folder = childs.next();
} else {
if( noCreate ){
// noCreateの場合はnullを返す
return undefined;
}else{
// フォルダが見つからなかった場合はフォルダを作成
folder = folder.createFolder( newFolder );
}
}
}
return folder;
}</pre></div></div>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-74508538111245773972022-02-23T22:27:00.044+09:002022-03-21T16:09:20.833+09:00G Suite アカウントを無料で継続利用する方法<h1 style="text-align: left;"><a href="https://blog.hikozaru.com/2022/03/g-suite-legacy.html">「Google Workspaceに課金せずデータを引き継ぐ」</a>に移動しました。</h1>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-54752431804203464772022-02-22T20:42:00.011+09:002022-02-23T11:20:43.238+09:00Googleスプレッドシートに書かれたデータに関してWEBからデータを取得するサンプルとしてGoogle Apps Scriptでスプレッドシートに書かれた郵便番号から住所を調べるスクリプトを作成した。郵便番号を取得するなら別の方法をお勧めする、あくまでGASの使い方説明の素材にしただけです。<div>エラー処理などを皆無だし、HTMLから必要なデータを抽出する部分も適当です。<div>スプレッドシートなどから呼び出した際にすぐに処理を抜けたい場合はstart関数を呼び出す、いきなり処理したい場合やデバッグ時はzipSearch関数を呼び出す。5分経過したらいったん中断し、1分後に処理を再開しまう。</div><div><br /></div><div>A:B列を取得してB列が空の行のみを処理します。すべて処理が終わるか5分経過するかで結果をスプレッドシートに書き込みます。都度書き込むとAPI呼び出し回数が増え、処理も遅くなります。</div><div><br /><div><div><br /><pre class="src">function start(){
// 1分後にスタート
setTrigger("zipSearch");
}
function zipSearch() {
// 一旦トリガを削除
clearTrigger( arguments.callee.name );
// スクリプト実行開始時間を取得(6分制限用)
var StartTime = new Date();
// シートから入出力部分を取得
// A列に郵便番号(”222-0001”)が入力されており、対応する住所をB列に入力する
let ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
let range = ss.getRange(1,1,ss.getLastRow(),2);
let values = range.getValues();
// 一行ずつ処理を実施
values.forEach( row =>{
if( row[0] != "" && row[1] == "" )
{
let url = "https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip="+row[0];
// 今回は<td class="data"><small>.*?</small></td>を抽出して処理
let table = UrlFetchApp.fetch(url)
.getContentText()
.match(/<td class="data"><small>.*?<\/small><\/td>/gis)
if( table!=null )
{
// 結合しタグを削除
row[1] = table.join(" ").replace(/<.*?>/gis,"");
}
else
{
row[1] = "error";
}
}
// スクリプト開始から5分経過したら一旦終了
var CurrentTime = new Date();
if( (CurrentTime - StartTime) > 5*60*1000 ){
// 結果をシートに書き戻す
range.setValues(values);
//トリガをセットして終了
setTrigger(arguments.callee.name);
return;
}
});
// 結果をシートに書き戻す
range.setValues(values);
}
function setTrigger(func)
{
trigger = ScriptApp.newTrigger(func)
.timeBased()
.everyMinutes(1)
.create();
}
function clearTrigger(func)
{
var triggers = ScriptApp.getProjectTriggers();
triggers.forEach( trigger=>{
if( trigger.getHandlerFunction() == func )
{
ScriptApp.deleteTrigger(trigger);
}
});
}</pre>
</div></div></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-18562846747152968972022-02-20T23:41:00.005+09:002022-02-22T11:48:52.623+09:00Googleドライブのフォルダに保存している画像をOCRしてドキュメントを生成する<p>画像をOCRして、画像とOCR結果が貼り込まれたドキュメントを生成するスクリプトです。</p>
<pre class="src">
function main() {
// マイドライブ\'GoogleAppsScript\dev\test-data\変換元データ
var srcFolder = getFolder( null, ['GoogleAppsScript','dev','test-data','変換前データ'], false );
var dstFolder = getFolder( null, ['GoogleAppsScript','dev','test-data','変換後データ'], false );
let option = {
"ocr": true,// OCRを行うかの設定です
"ocrLanguage": "ja",// OCRを行う言語の設定です
}
var files = srcFolder.getFiles();
while( files.hasNext() )
{
var file = files.next();
var resource = {
title: file.getName()
};
let doc = DriveApp.getFileById( Drive.Files.copy(resource, file.getId(), option).id);
doc.moveTo( dstFolder );
}
}
/**
* 指定されたフォルダ取得する、フォルダがないときは新規に作成する。
*
* @param {Folder} parent 基準フォルダ、null指定時はルートフォルダ
* @param {string|Array of strings} name 取得・生成するフォルダ名
* string 指定時はnameを取得。生成する
* Array of strings 指定時は多階層フォルダを一括作成
* @param {bool} noCreate 作成は行わず既存のフォルダを取得するときにtrue
* 省略可能、省略時はfalseとして動作
* @return {Folder|undefined} 取得・生成したフォルダ
*/
function getFolder( parent, name, noCreate ) {
// 親フォルダが指定されなかった場合はルートフォルダを取得する。
if ( parent == null ){
var folder = DriveApp.getRootFolder();
}else{
var folder = parent;
}
// フォルダ名に配列が指定されていない場合は配列にする。
if( !Array.isArray( name ) ){
name = [name];
}
// noCreateが指定されていない場合はfalseにする。
if ( noCreate !== true ){
noCreate = false;
}
while( name.length > 0 ){
var newFolder = name.shift();
var childs = folder.getFoldersByName( newFolder );
if( childs.hasNext() ){
// フォルダが見つかった場合は最初のフォルダを採用
folder = childs.next();
} else {
if( noCreate ){
// noCreateの場合はnullを返す
return undefined;
}else{
// フォルダが見つからなかった場合はフォルダを作成
folder = folder.createFolder( newFolder );
}
}
}
return folder;
}
</pre>
hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com5tag:blogger.com,1999:blog-4133168287384904096.post-17679822793521136412022-02-12T14:12:00.005+09:002022-02-22T15:48:23.667+09:00AdSenseのデータをスプレッドシートに書き込むスクリプト以下のスクリプトを実行するとAdSenseのデータをスプレッドシートに取り込みます。
未取得分だけを取得して追加するので、時間駆動のトリガで1時間おきにでも実施するのが良いです。
取り込んだデータはスプレッドシート側でデータ集計したり、グラフを作成してください。
<pre class="src">function myFunction() { // 1時間おきのトリガを設定したい場合はこちらを実行
trigger = ScriptApp.newTrigger("report")
.timeBased()
.everyHours(1)
// .everyMinutes(5)
.create();
report();
}
function report() {
var adsenseClientID = 'ca-pub-NNNNNNNNNNNNNNNN';
var adsenseAccounts = 'pub-NNNNNNNNNNNNNNNN';
var <b>metrics = ['ESTIMATED_EARNINGS', 'PAGE_VIEWS', 'CLICKS', 'PAGE_VIEWS_CTR', 'COST_PER_CLICK', 'PAGE_VIEWS_RPM'];
</b> var sheetName = 'report';
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetName);
if (sheet == null) {
sheet = ss.insertSheet(sheetName);
}
const today = new Date();
var lastRow = sheet.getLastRow();
if (lastRow < 2) {
var last = new Date('1900/1/1');
sheet.getRange(1, 1, 1, metrics.length+1).setValues([['Date'].concat(metrics)]);
lastRow = 2;
}
else {
var last = new Date(sheet.getRange(sheet.getLastRow(), 1).getDisplayValue());
}
var report = <b>AdSense.Accounts.Reports.generate</b>(
'accounts/'+adsenseAccounts,
{
// Specify the desired ad client using a filter.
filters: ['AD_CLIENT_ID=='+adsenseClientID],
metrics: metrics,
<b>dimensions: ['DATE']</b>,
dateRange: 'CUSTOM',
'startDate.year': last.getFullYear(),
'startDate.month':last.getMonth() + 1,
'startDate.day':last.getDate(),
'endDate.year': today.getFullYear(),
'endDate.month':today.getMonth() + 1,
'endDate.day':today.getDate(),
// Sort by ascending date.
reportingTimeZone: 'ACCOUNT_TIME_ZONE',
orderBy: ['+DATE']
} );
sheet.getRange(lastRow, 1, report.rows.length, report.rows[0].cells.length)
.setValues(report.rows.map(row => row.cells.map(cell => cell.value)));
}
</pre>
<p>Reports.generate関数は<a href="https://developers.google.com/adsense/management/reference/rest/v2/accounts.reports/generate" target="_blank">ヘルプ(Method: accounts.reports.generate)</a>を、metricsやdimensionsに指定する値は<a href="https://developers.google.com/adsense/management/metrics-dimensions" target="_blank">ヘルプ(Metrics and Dimensions)</a>を参照してください。</p>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-15050918579490644072022-02-07T20:19:00.004+09:002022-02-07T20:34:21.120+09:00厚生労働省のオープンデータから新規陽性者数の推移(日別)を取得してスプレッドシートに書き込むスクリプト<p>厚生労働省のオープンデータから新規陽性者数の推移(日別)を取得してスプレッドシートに書き込む処理を毎日行うGoogle Apps Script</p>
<pre class="src">function myFunction() {
trigger = ScriptApp.newTrigger("scraping")
.timeBased()
.everyDays(1)
.create();
scraping();
}
function scraping() {
var content = UrlFetchApp.fetch("https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv").getContentText();
var values = Utilities.parseCsv(content);
var sheet = SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName('シート1');
sheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
</pre>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-5295873384676227982022-02-06T16:27:00.016+09:002022-02-07T19:01:57.174+09:00GoogleAppsScriptを使用しHTML内のテーブルをスプレッドシートに書き込む<h2>Googleドライブの特定のフォルダに格納されているHTMLファイルの中に記載されているテーブルをスプレッドシートに書き込むスクリプト</h2>
<p>どんな利用シーンがあるか分かりませんが、<a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14256594859" target="_blank">知恵袋で質問</a>があったので作成してみた。なにかのツールが吐き出す結果のHTMLファイルにテーブルが含まれていて、その結果をシートにまとめたいという要望だと思う。</p><p>まったく同じようなシーンはあまり考えにくいが、何かの役に立つかもしれないので自分用のメモ代わりに残しておく。</p><p>6分越え対策やテーブルタグ(<tr>や<td>)内のデータ抽出などもふくめてエラー処理などかなり雑です、コメントで指摘してくれたら修正するかもしれません。</p><p><br /></p>
<p>ソースコード</p>
<pre class="src">function myFunction() {
// HTMLファイルが格納されているフォルダ階層を配列形式で指定する。
// マイドライブ/AAA/BBB/ フォルダを指定するときは["AAA","BBB"]と指定する。
var srcFolder = getFolder( null,["GoogleAppsScript","dev","HTML内の表を抜き出す","未処理"]);
// HTMLファイルが格納されているフォルダ階層を配列形式で指定する。
var dstFolder = getFolder( null,["GoogleAppsScript","dev","HTML内の表を抜き出す","処理済み"]);
// スプレッドシートの指定は環境に合わせてください。
var sheet = SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName('シート1');
// スプレッドシートに書き込む二次元配列
var table = [];
// 一気に処理すると6分で終わらないので適当な回数で区切る。
// 数が多いときは時間主導のトリガで繰り返し実行するとよい。
var numberOfFiles = 50;
var htmlFiles = srcFolder.getFiles();
while (htmlFiles.hasNext()) {
// 指定したファイル数の処理が完了したら抜ける。
numberOfFiles--;
if( numberOfFiles < 0 ){
break;
}
var file = htmlFiles.next();
var text = file.getBlob().getDataAsString();
// ここからが必要なデータの取り出しとシートへの貼り込み
// <tr></tr>の抜き出して1行分を取り出す。
var rows = text.match(/<tr(?:\s.+?)?>.*?<\/tr\s*?>/gis);
for( var r=0; r<rows.length; r++ )
{
// 1行分の配列
var arrayCols = [];
// <th></th>もしくは<td></td>を抜き出す。
var cols = rows[r].match(/(<th(?:\s.+?)?>.*?<\/th\s*?>)|(<td(?:\s.+?)?>.*?<\/td\s*?>)/gis);
for( var c=0; c<cols.length; c++ )
{
// <th>,</th>,<td>,</td>を削除して配列に格納する
arrayCols.push( cols[c].replace(/^(<(td|th)(?:\s.+?)?>)|(<\/(td|th)\s*?>$)/ig,""));
}
// 1行分の配列を追加
table.push(arrayCols);
}
// 処理が完了したファイルは処理済みフォルダに移動
file.moveTo( dstFolder );
}
// ファイル移動と書き込みは同じ場所が理想
// 処理高速化を考えてファイル移動はループ内
// スプレッドシートへの書き込みはループの外に移動
sheet.getRange(sheet.getLastRow()+1,1,table.length,table[0].length).setValues(table);
}
/**
* 指定されたフォルダ取得する、フォルダがないときは新規に作成する。
*
* @param {Folder} parent 基準フォルダ、null指定時はルートフォルダ
* @param {string|Array of strings} name 取得・生成するフォルダ名
* string 指定時はnameを取得。生成する
* Array of strings 指定時は多階層フォルダを一括作成
* @param {bool} noCreate 作成は行わず既存のフォルダを取得するときにtrue
* 省略可能、省略時はfalseとして動作
* @return {Folder|undefined} 取得・生成したフォルダ
*/
function getFolder( parent, name, noCreate ) {
// 親フォルダが指定されなかった場合はルートフォルダを取得する。
if ( parent == null ){
var folder = DriveApp.getRootFolder();
}else{
var folder = parent;
}
// フォルダ名に配列が指定されていない場合は配列にする。
if( !Array.isArray( name ) ){
name = [name];
}
// noCreateが指定されていない場合はfalseにする。
if ( noCreate !== true ){
noCreate = false;
}
while( name.length > 0 ){
var newFolder = name.shift();
var childs = folder.getFoldersByName( newFolder );
if( childs.hasNext() ){
// フォルダが見つかった場合は最初のフォルダを採用
folder = childs.next();
} else {
if( noCreate ){
// noCreateの場合はnullを返す
return undefined;
}else{
// フォルダが見つからなかった場合はフォルダを作成
folder = folder.createFolder( newFolder );
}
}
}
return folder;
}</pre>
<p>1つ目のHTMLファイル</p>
<pre class="src"><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ひこざるさん</title>
</head>
<body>
<a href="https://blog.hikozaru.com">ひこざるさんのブログ</a>
<table border="1">
<tr>
<th>XXX</th>
<th>YYY</th>
<th>zzz</th>
</tr>
<tr>
<td>111X</td>
<td>111Y</td>
<td>111Z</td>
</tr>
</table>
</body>
</html></pre>
<p>2つ目のHTMLファイル</p>
<pre class="src"><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ひこざるさん</title>
</head>
<body>
<a href="https://blog.hikozaru.com">ひこざるさんのブログ</a>
<table border="1">
<tr>
<th>XXX</th>
<th>YYY</th>
<th>zzz</th>
</tr>
<tr>
<td>222X</td>
<td>222Y</td>
<td>222Z</td>
</tr>
</table>
</body>
</html></pre>
<p>実行結果</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg_i-1AvtDAS7xNkIJPiArhNnktB62NntIsi_W2GFK7SmeG20ScYdc5SihtUI8Ct5_j4z6JCW8LJSIt_93wsU8iAjEe-f9vYnitGdXAFK9Smm3YBrur4bvKSeo_YLye0NnjF28Ae1Q_tg9A-Nqi6ULUymJODOFgroROEife4wLymDHVEyqeNbKAl_G-dA=s380" style="display: block; padding: 1em 0px; text-align: center;"><img alt="" border="0" data-original-height="185" data-original-width="380" src="https://blogger.googleusercontent.com/img/a/AVvXsEg_i-1AvtDAS7xNkIJPiArhNnktB62NntIsi_W2GFK7SmeG20ScYdc5SihtUI8Ct5_j4z6JCW8LJSIt_93wsU8iAjEe-f9vYnitGdXAFK9Smm3YBrur4bvKSeo_YLye0NnjF28Ae1Q_tg9A-Nqi6ULUymJODOFgroROEife4wLymDHVEyqeNbKAl_G-dA=s400" width="400" /></a></div>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-41900991498412701572022-02-05T19:30:00.003+09:002022-02-05T19:34:56.047+09:00部活で共有しているアカウントにプライベート写真がアップロードされたかもしれない場合<p style="text-align: left;">部活、サークル、職場などの共有アカウントのGoogleフォト写真が登録されてしまって、皆に見られているかもしれない。という質問は結構多い。</p><p style="text-align: left;">根本的にアカウントを共有するのが大変危険です。その際の対処を書きますので、以下の順番で確認および対応を行ってください。</p><h2 style="text-align: left;">1.スマホのGoogleフォトアプリの設定を確認</h2><div><br /></div><div>Googleフォトアプリの右上のアカウントアイコンをタップしてください。</div><div>「フォトの設定」⇒「バックアップと同期」画面に遷移して「バックアップアカウント」を確認してください。</div><div>そのアカウントが共有アカウントだとしたらヤバいです、その画面で「バックアップと同期」をオフするか、プライベートアカウントに切り替えてください。</div><div><br /></div><h2 style="text-align: left;">2.他の人が見える画像を確認</h2><div><div><br /></div><div>スマホのSafariブラウザのプライベートタブやChromeブラウザのシークレットモードでGoogleフォトWEB版(<a href="https://photos.google.com/login">https://photos.google.com/login</a>)に共有アカウントでログインしてください。</div></div><div>プライベートタブやシークレットモードでアクセスしないと別の問題が発生するので、もしわからなければWEBで調べてください。</div><div>GoogleフォトWEB版でのアクセスに成功すると左上が「≡」アイコンになっています。</div><div>そこで表示されている画像が、共有アカウントにログインできる人が閲覧可能な画像です。そこに画像が表示されていたら次の手順に進んでください。</div><div><br /></div><h2 style="text-align: left;">3.公開されてしまった画像を削除</h2><div><br /></div><div>上の1.と2.の手順を実施してから本手順を実施してください。</div><div>手順2.と同じ手順でGoogleフォトWEB版(<a href="https://photos.google.com/login">https://photos.google.com/login</a>)に共有アカウントでログインしたらプライベート画像をゴミ箱アイコンでゴミ箱に入れてください。</div><div>ゴミ箱から完全に削除する前に端末に画像が残っているか確認してください。</div><div>確認はGoogleフォトアプリ以外のgallery goなど端末のデータを閲覧するアプリで行ってください。</div><div>端末から削除されていないことを確認したらGoogleフォトWEB版で「≡」⇒「ゴミ箱」に行き、ゴミ箱を空にしてください。</div><div><br /></div>hikochanghttp://www.blogger.com/profile/10117214007987013340noreply@blogger.com0tag:blogger.com,1999:blog-4133168287384904096.post-87478300262925661332022-01-25T06:53:00.008+09:002023-12-05T05:21:17.107+09:00Googleフォトのデータを削除して容量を空ける以下に該当する画像は容量を消費してないので削除しても空き容量は増えません。<div><br /><div> ①2021/5/31までに高画質設定でバックアップした画像 </div><div> ②2021/5/31までに容量を解放を実施した場合は、実施前にバックアップした画像 </div><div>③2022/1/31までにpixel3からバックアップした画像 </div><div>④pixel5までのpixelシリーズのGoogleフォトアプリで節約画質(旧 高画質)設定でバックアップした画像 </div><div>⑤パートナー共有された画像を自分のライブラリに保存した画像(これが容量カウントされないのはバグだと思います、ある日突然容量消費する可能性が有ります) </div><div><br /></div><div>上記に該当しない画像を消すと空き容量が増えます。上記に該当する写真を消すと空き容量が増えてしまうこともあります。</div><div><br /></div><div>なお、削除に関しては <a href="https://blog.hikozaru.com/2019/11/GooglePhotosDelete.html">https://blog.hikozaru.com/2019/11/GooglePhotosDelete.html </a>の2-1や2-2を参照下さい</div></div>Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4133168287384904096.post-33724725499895759132022-01-16T12:44:00.009+09:002022-01-16T13:56:41.146+09:00JavaScriptのforEachが良く分からないという質問に対する回答<div>for( var i=0; i<array.length; i++){console.log(array[i];}は理解しているけど、<br />
array.forEach(element => {console.log(element);});はよくわからないという方向けの説明です。<br /></div>
<div>forEach の書き方は検索すれば大量にヒットするのですが、それでもこの書式の意味が良く分からないという方は一定数いるのではないでしょうか。ヤフー知恵袋でまさにその<a href="https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10255459570" target="_blank">質問</a>があったので回答してみたのでその紹介です。</div>
<div>質問内容としては以下です。
<pre>
forEachメソッドについて
const numbers=[1,2,3];
numbers.forEach((number) =>{console.log(number);});
ここの引数の使い方がいまいち理解できません。
numberが定義されていないのになぜこれでちゃんと出力されるのですか?
</pre>
</div>
<div>私が初めてこの書き方を見たときと同じ疑問です。<br /></div>
<div>forEachの構文や正確な情報は <a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" target="_blank">MDN Web DocsのArray.prototype.forEach()の説明</a> などを見ていただければよいかと思います。<br /></div>
<div>今回は for を forEach に書き換えていくことで構文を覚えるのではなく、理解するということを目指していく。<br /></div><div><br /></div>
<div><h3>①forを用いた記述</h3>
<div>これが分からない人は、ごめんなさいこれ以上読み進めても意味がないです。</div>
<pre class="src">function test()
{
var array=[1,2,3,4,5];
for( var i=0; i < array.length; i++ )
{
console.log( array[i] );
}
}</pre>
<br />
<h3>②forの処理を関数化</h3>
<pre class="src"><b>function hogehoge( number )
{
console.log( number );
}</b>
function test()
{
var array=[1,2,3,4,5];
for( var i=0; i < array.length; i++ )
{
<b>hogehoge( array[i] );</b>
}
}
</pre>
<br />
<h3>③コールバック関数風に書き換え</h3>
<div>あまり利点はないですが説明のための変形です。</div>
<pre class="src">function hogehoge( number )
{
console.log( number );
}
function test()
{
var array=[1,2,3,4,5];
<b>var callbackFunction = hogehoge;</b>
for( var i=0; i < array.length; i++ )
{
<b>callbackFunction( array[i] );</b>
}
}
</pre>
<br />
<h3>④for文自体を関数化</h3>
<div>forEach風の関数を作成します。</div>
<pre class="src">function hogehoge( number )
{
console.log( number );
}
<b>function forEachFunction( array, callbackFunction )
{
for( var i=0; i<array.length; i++)
{
callbackFunction( array[i] );
}
}</b>
function test()
{
var <b>numbers</b>=[1,2,3,4,5];
<b>forEachFunction( numbers, hogehoge );</b>
}
</pre>
<br />
<h3>⑤forEachに書き換える</h3>
<div>forEach風の関数をforEachに書き換えます。</div>
<pre class="src">function hogehoge( number )
{
console.log( number );
}
function test()
{
var numbers=[1,2,3,4,5];
<b>numbers.forEach( hogehoge );</b>
}
</pre>
<br />
<h3>⑥forEachの中で関数を定義する</h3>
<div>forEachのたびに別関数を作ると読みにくくなるので、関数定義しつつコールバック関数登録します。</div>
<pre class="src">function test()
{
var numbers=[1,2,3,4,5];
numbers.forEach(
<b>function hogehoge(number){console.log(number);}</b>
);
}
</pre>
<br />
<h3>⑦アロー関数で定義する</h3>
<div>関数定義をアロー関数に書き換えます。</div>
<pre class="src">function test()
{
var numbers=[1,2,3,4,5];
numbers.forEach(
<b>number=>{console.log(number);}</b>
);
}
</pre>
<br />
<h4>●アロー関数は以下を見てください。</h4>
<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions" target="_blank">https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions</a>
</div>Anonymousnoreply@blogger.com0