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);
}
});
}
2022年2月22日火曜日
Googleスプレッドシートに書かれたデータに関してWEBからデータを取得する
2022年2月20日日曜日
Googleドライブのフォルダに保存している画像をOCRしてドキュメントを生成する
画像をOCRして、画像とOCR結果が貼り込まれたドキュメントを生成するスクリプトです。
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;
}
2022年2月12日土曜日
AdSenseのデータをスプレッドシートに書き込むスクリプト
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 metrics = ['ESTIMATED_EARNINGS', 'PAGE_VIEWS', 'CLICKS', 'PAGE_VIEWS_CTR', 'COST_PER_CLICK', 'PAGE_VIEWS_RPM'];
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 = AdSense.Accounts.Reports.generate(
'accounts/'+adsenseAccounts,
{
// Specify the desired ad client using a filter.
filters: ['AD_CLIENT_ID=='+adsenseClientID],
metrics: metrics,
dimensions: ['DATE'],
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)));
}
Reports.generate関数はヘルプ(Method: accounts.reports.generate)を、metricsやdimensionsに指定する値はヘルプ(Metrics and Dimensions)を参照してください。
2022年2月7日月曜日
厚生労働省のオープンデータから新規陽性者数の推移(日別)を取得してスプレッドシートに書き込むスクリプト
厚生労働省のオープンデータから新規陽性者数の推移(日別)を取得してスプレッドシートに書き込む処理を毎日行うGoogle Apps Script
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);
}
2022年2月6日日曜日
GoogleAppsScriptを使用しHTML内のテーブルをスプレッドシートに書き込む
Googleドライブの特定のフォルダに格納されているHTMLファイルの中に記載されているテーブルをスプレッドシートに書き込むスクリプト
どんな利用シーンがあるか分かりませんが、知恵袋で質問があったので作成してみた。なにかのツールが吐き出す結果のHTMLファイルにテーブルが含まれていて、その結果をシートにまとめたいという要望だと思う。
まったく同じようなシーンはあまり考えにくいが、何かの役に立つかもしれないので自分用のメモ代わりに残しておく。
6分越え対策やテーブルタグ(<tr>や<td>)内のデータ抽出などもふくめてエラー処理などかなり雑です、コメントで指摘してくれたら修正するかもしれません。
ソースコード
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;
}
1つ目のHTMLファイル
<!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>
2つ目のHTMLファイル
<!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>
実行結果
2022年2月5日土曜日
部活で共有しているアカウントにプライベート写真がアップロードされたかもしれない場合
部活、サークル、職場などの共有アカウントのGoogleフォト写真が登録されてしまって、皆に見られているかもしれない。という質問は結構多い。
根本的にアカウントを共有するのが大変危険です。その際の対処を書きますので、以下の順番で確認および対応を行ってください。
1.スマホのGoogleフォトアプリの設定を確認
2.他の人が見える画像を確認
3.公開されてしまった画像を削除
2022年1月25日火曜日
Googleフォトのデータを削除して容量を空ける
フォト
2022年1月16日日曜日
JavaScriptのforEachが良く分からないという質問に対する回答
array.forEach(element => {console.log(element);});はよくわからないという方向けの説明です。
forEachメソッドについて
const numbers=[1,2,3];
numbers.forEach((number) =>{console.log(number);});
ここの引数の使い方がいまいち理解できません。
numberが定義されていないのになぜこれでちゃんと出力されるのですか?
①forを用いた記述
function test()
{
var array=[1,2,3,4,5];
for( var i=0; i < array.length; i++ )
{
console.log( array[i] );
}
}
②forの処理を関数化
function hogehoge( number )
{
console.log( number );
}
function test()
{
var array=[1,2,3,4,5];
for( var i=0; i < array.length; i++ )
{
hogehoge( array[i] );
}
}
③コールバック関数風に書き換え
function hogehoge( number )
{
console.log( number );
}
function test()
{
var array=[1,2,3,4,5];
var callbackFunction = hogehoge;
for( var i=0; i < array.length; i++ )
{
callbackFunction( array[i] );
}
}
④for文自体を関数化
function hogehoge( number )
{
console.log( number );
}
function forEachFunction( array, callbackFunction )
{
for( var i=0; i<array.length; i++)
{
callbackFunction( array[i] );
}
}
function test()
{
var numbers=[1,2,3,4,5];
forEachFunction( numbers, hogehoge );
}
⑤forEachに書き換える
function hogehoge( number )
{
console.log( number );
}
function test()
{
var numbers=[1,2,3,4,5];
numbers.forEach( hogehoge );
}
⑥forEachの中で関数を定義する
function test()
{
var numbers=[1,2,3,4,5];
numbers.forEach(
function hogehoge(number){console.log(number);}
);
}
⑦アロー関数で定義する
function test()
{
var numbers=[1,2,3,4,5];
numbers.forEach(
number=>{console.log(number);}
);
}
●アロー関数は以下を見てください。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions2022年1月15日土曜日
Googleフォトに写真が見当たらない場合
考えられる原因は2つです。
- バックアップできていなかった
- Googleフォトアプリに表示されていてもバックアップできているとは限りません。そこを勘違いする人が多いです。
- Googleフォトをインストールしてもバックアップには時間がかかります、1日15GBまでしかバックアップできないので100GBとか保存している場合には1週間くらいかかります。「携帯ショップで作業してくれた」という状況の場合はバックアップできてない可能性が高いです。
- アカウントが違う
1.アカウントを確認する
所有しているアカウントすべてを確認:
以下のヘルプに従い所有しているアカウントすべてを確認してください
存在するアカウントについて確認する(https://support.google.com/accounts/answer/40560?hl=ja)
旧端末が手元にある場合:
旧端末が手元にある場合は念のため、旧端末のGoogleフォトアプリで右上のアカウントアイコンから「フォトの設定」→「バックアップと同期」と進みバックアップ先のアカウントを確認してください。
2.WEB版のGoogleフォトでデータを確認する
Androidの場合:
Chromeブラウザのシークレットモードで https://photos.google.com/login にログインして画像を確認してください。
左上の「≡」アイコンから、「フォト」「アーカイブ」「ゴミ箱」「設定➜サポートされていない動画」の四か所を確認してください。
複数のアカウントを所有している場合には、すべてのアカウントでログインしてください。別のアカウントでログインする場合には一旦タブを閉じて新しいタブで同様にログインしなおしてください。
iPhoneの場合:
Safariブラウザのプライベートタブで https://photos.google.com/login にログインして画像を確認してください。
左上の「≡」アイコンから、「フォト」「アーカイブ」「ゴミ箱」「設定➜サポートされていない動画」の四か所を確認してください。複数のアカウントを所有している場合には、すべてのアカウントでログインしてください。別のアカウントでログインする場合には一旦タブを閉じて新しいタブで同様にログインしなおしてください。
ログインできない場合:
以下を参考にログインを試みてください。
3.アルバムアーカイブでデータを確認する(この機能はなくなってしまいました)
Androidの場合:
Chromeブラウザのシークレットモードで https://get.google.com/albumarchive/ にアクセスして画像を確認してください。
左上の「≡」アイコンから、「フォト」「アーカイブ」「ゴミ箱」の三か所を確認してください。
複数のアカウントを所有している場合には、すべてのアカウントでログインしてください。別のアカウントでログインする場合には一旦タブを閉じて新しいタブで同様にログインしなおしてください。
iPhoneの場合:
Safariブラウザのプライベートタブで https://get.google.com/albumarchive/ にアクセスして画像を確認してください。
左上の「≡」アイコンから、「フォト」「アーカイブ」「ゴミ箱」の三か所を確認してください。複数のアカウントを所有している場合には、すべてのアカウントでログインしてください。別のアカウントでログインする場合には一旦タブを閉じて新しいタブで同様にログインしなおしてください。
4.Googleフォトでデータが見つからない場合/データが足りない場合
旧端末が手元にある場合:
以下のヘルプを参考に旧端末でバックアップを行ってください。Androidの場合はデバイスのフォルダをバックアップする方法の説明もよく読んでください。
写真や動画をバックアップする (https://support.google.com/photos/answer/6193313?hl=ja)
容量が不足していると 中途半端にしかバックアップできません、以下でバックアップ先アカウントの容量を確認してください。空き容量がない場合はGoogle Oneに加入し必要な容量を購入してください。
なお、旧端末から写真を消してもよい場合には以下の方法で確実にバックアップすることをお勧めします。
機種変更時に写真をGoogleフォトにBackupする方法(https://blog.hikozaru.com/2018/04/iphonegooglebackup.html)
旧端末が手元にない場合:
バックアップできていなかった可能性もあります、その場合はGoogleフォトからの復元は無理です。アカウントが違う可能性もあるので最初の手順から繰り返してください。
2022年1月3日月曜日
GoogleフォトのHEIC画像をJPGでダウンロードするオプション
iPhoneで撮影したHEIC画像をGoogleフォトにバックアップしWEB素材で使用する際にHEICからJPGへの変換が必要になる。私は別の用途だったのでこのオプションは使えないと思い込んでいましたが、人によっては有用ということが分かったので説明します。
Googleフォト上で画像を編集してからダウンロードするとJPGに変換できるが、編集するのは少し気持ち悪いし手間がかかる。
パソコンでダウンロードするときにJPEGでダウンロードするオプションを紹介する、といってもGoogleが公式に公開しているBase URLsのドキュメント通りにオプションを設定するだけ。注意事項としては位置情報が消されるということですが、WEB素材で使用する場合などはかえって都合がよいのではないでしょうか。
手順
- GoogleフォトでHEIC画像を表示する。
- 画像を右クリックして「新しいタブで画像を開く」を行う。
- 新しいタブのURLの末尾を確認する。
- 末尾のオプションを変更してJPGファイルをダウンロードする。
”=wXXX-hYYY-no?” ⇒ "=d?" と書き換えるだけです。