LANG SELRCT

Google Apps Scriptのコードを書く場所  (新規作成: スプレッドシート | スクリプトエディタ

2021年5月23日日曜日

マイドライブを指定してファイルを保存したい(DriveApp.getRootFolder())


以前書いた

CSVデータを作ってGoogleドライブに保存する

では、特定のフォルダを指定して保存しました。

ここでは「マイドライブ」に保存するコードを書きました。


save_as_csv()を実行すると

マイドライブにvar dataで設定したデータが保存されて

そのファイルのURLがログに出力されます。



コード.gs
function save_as_csv() {
  var data = "でーた1, でーた2\nでーた3";
  create_file(data);
}

function create_file(data) {
  var content_type = "text/csv";
  var file_name = "FILE_NAME";
  var blob = Utilities.newBlob("", content_type, file_name);
  var file = blob.setDataFromString(data, "UTF-8");
  var folder = DriveApp.getRootFolder();
  var file = folder.createFile(file);
  var fileUrl = file.getUrl();
  Logger.log(fileUrl);
}




2021年5月5日水曜日

JavaScriptのanimate()でアニメーションを試してみたい


Elementの透明度と位置をアニメーションさせたい。

Element.animate() で実装できました。


デモ




コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}
意訳
この機能がやること
指定したHTMLファイルを表示する




index.html
<!DOCTYPE html>
<html>

<body>
<textarea id="ta">hello</textarea>
<script>

animation();
function animation() {
  elem("ta").animate({
    "opacity": [ 0, 1 ], // [ フレーム 1, フレーム 2 ]
    "color": [ "#fff", "#000" ] // [ フレーム 1, フレーム 2 ]
    },
    {
      "duration": 2000,
      "iterations": Infinity
    })

  elem("ta").animate({
    "marginLeft": ["0px", "100px"]
    },
    {
      "duration": 1000,
      "easing": "ease",
      "iterations": Infinity
    })
  
  // 移動後の位置を設定しないと元に戻る
  elem("ta").style.marginLeft = "100px";
}

function elem(id) {
  return document.getElementById(id);
}

</script>
</body>
</html>



参考

Element.animate()

Animation

Keyframe Formats

EffectTiming

2021年5月4日火曜日

Google Apps ScriptでURLの表示を変更したい google.script.history.replace()


google.script.history.replace()

で実現できました。


こういうことを実現したい

HtmlServiceのWebアプリのURL
https://script.google.com/macros/s/ID/exec

ページ遷移を発生させずパラメーターを追加したい
https://script.google.com/macros/s/ID/exec?id=1&value=hello



URLの表示を変更したくて調べてみると、History API を取り扱う が見つかりました。
試してみると、history.pushState() や history.replaceState() では変更できなかった。

さらに調べてみると Class google.script.history (Client-side API) が見つかりました。

google.script.history.push() と google.script.history.replace() で実現できました。
pushとreplaceの違いはリファレンスを参照してください。

今回は replace() を使ったコードを書きました。



コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}
意訳
この機能がやること
指定したHTMLファイルを表示する




index.html
<!DOCTYPE html>
<html>
<body>

<script>

replaceParam();
function replaceParam() {
  var params = {
    "id": 1,
    "value": "hello"
  };
  google.script.history.replace("", params, "");
}
</script>

</body>
</html>




参考

Class google.script.history (Client-side API) 

History API を取り扱う


2021年4月30日金曜日

[Spreadsheet] 列ごとに値をユニークにしてオブジェクト化したい(2列目は配列で持つ)


以下のような処理を実現したくて書きました。


スプレッドシートのA、B列に以下のようなデータがある時
prefecturecity
東京新宿
東京新宿
東京渋谷
東京渋谷
東京品川
東京品川
東京品川
東京品川
神奈川横浜
神奈川横浜
神奈川横浜
神奈川横浜
神奈川川崎
神奈川川崎


それぞれの列で重複する値をユニークにして
以下のようなオブジェクトにしたい。

 {東京=[新宿, 渋谷, 品川], 神奈川=[横浜, 川崎]}

A列はオブジェクトのkey。
B列は配列で持つ。



コード.gs
function myFunction() {
  var categoriesObj = createCategoriesObj();
  Logger.log(categoriesObj);
}
/************************************
オブジェクトを作成する
************************************/
function createCategoriesObj() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var lastRow = sheet.getLastRow();
  var categories = sheet.getRange(1, 1, lastRow, 1).getValues();
  var subCategories = sheet.getRange(1, 2, lastRow, 1).getValues();
  
  // ヘッダ行の要素は取り除いておく
  categories.shift();
  subCategories.shift();
  
  // ここからオブジェクトを作っていく
  var obj = {};
  var array = [];
  for(var i = 0; i < categories.length; i++) {
    var category = categories[i][0];
    var categoryPrev = categories[i-1];
    if(obj[category] !== obj[categoryPrev]) {//categoryの値が変わった時に配列を初期化したい
      array = [];// 初期化しないと要素が追加され続ける
    }
    array.push(subCategories[i][0]);
    obj[category] = array.filter(returnUnique);// subCategoriesの値が重複してもここでuniqueにする
  }
  return obj;
}

/************************************
一次元配列の要素の値をユニークにする
************************************/
function returnUnique(value_i, index, array){
  var value_i_index = array.indexOf(value_i);// 配列の何番目に要素があるかを先頭の要素から一つずつ確認して
  var result = value_i_index === index;// 配列の要素のindexと同じなら
  return result;// その値を返して配列に追加する(違うなら追加しない→2つ目以降は存在してもindexが異なるため追加されない)
}



myFunctionを実行すると以下のようなログが出力されます。

2021年4月25日日曜日

テキストの改行を削除したい


改行を含むテキストから改行を削除したくて書いたコードです。

ここでは

text.replace(/\n/g, "")

で改行を削除しています。


デモアプリ
上のテキストエリアにテキストを貼り付けると
改行が削除されたテキストが下に出力されます。






コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}
意訳
この機能がやること
指定したHTMLファイルを表示する




index.html
<!DOCTYPE html>
<html>
<body>
  <textarea id="ta" style="width:30vw; height:30vh"></textarea>
  <br>
  <textarea id="result_ta" style="width:30vw; height:30vh"></textarea>

<script>
document.getElementById("ta").onkeyup = taKeyup;

function taKeyup() {
  var text = document.getElementById("ta").value;
  var result = text.replace(/\n/g, "");
  document.getElementById("result_ta").value = result;
}

</script>
</body>
</html>





2021年3月2日火曜日

選択したテキストを配列に入れてテキストエリアに出力したい


今回やりたいこと

アプリケーションの中で
選択したテキストを取得する。

選択したテキストを
テキストエリアに入れる。

選択したテキストを
配列に追加していく。



STEP1
「テキストを」を選択するとテキストエリアに「テキストを」が入る。


STEP2
その後、「追加して」を選択するとテキストエリアに「テキストを,追加して」が入る。



コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}
意訳
この機能がやること
指定したHTMLファイルを表示する




index.html
<!DOCTYPE html>
<html>
  <body>
    選択した範囲のテキストを配列に追加してテキストエリアに入れる。
    <textarea id="ta"></textarea>

<script>
document.onmouseup = on_mouseup;

var values = [];

function on_mouseup() {
  var text = window.getSelection();
  values.push(text.toString());
  document.getElementById("ta").value = values;
}

</script>

  </body>
</html>



JIRAのカンバンボードで次世代プロジェクトの課題が表示されないときは、サブフィルターを空にしてみる


(コードを使う話ではありません)

クラシック・次世代、両プロジェクトの課題を一つのカンバンボードに表示したい。

と思ってやってみたら
次世代プロジェクトの課題が表示されないという壁にぶつかりました。


解決方法

カンバン ボード サブフィルターに入っている
fixVersion in unreleasedVersions() OR fixVersion is EMPTY
を削除する。


今回やった手順

STEP1
ボード設定の「基本メニュー」の下の方に
カンバン ボード サブフィルター があります。


STEP2
フィルタの条件部分にマウスポインタを移動すると
右端に鉛筆アイコンが表示されます。
それをクリックして編集します。


STEP3
fixVersion in unreleasedVersions() OR fixVersion is EMPTY
という条件を削除して「更新」をクリックします。


サブフィルタがありません
という状態になります。

これで
クラシック・次世代、両プロジェクトの課題を一つのカンバンボードに表示できました。


補足

サブフィルターの設定だけでなく、「列」のマッピングも確認
  1. ボード設定の「列」を開きます
  2. 右端の「課題を含むステータス」を確認します
  3. 対象のステータスの課題がそこにあると、ボードの列に表示されません
  4. 表示したい列にドラッグ&ドロップして追加すると、ボードに表示されます





「列」のマッピングをしているのに
次世代プロジェクトの課題がボードに表示されない場合は
本投稿のカンバン ボード サブフィルターを空にすると表示されるようになるかも。


参考

Any way to include next-gen issues in a classic board ?
https://community.atlassian.com/t5/Jira-questions/Any-way-to-include-next-gen-issues-in-a-classic-board/qaq-p/1012688

2021年2月28日日曜日

Google Apps Scriptでトリガーを作成したい(1分後に実行して自動で削除する after(1000 * 60))


timeBased().after()を使ってみる。



コード.gs
function setTrigger() {
  const trigger = ScriptApp.newTrigger('myFunction')
    .timeBased()
    .after(1000 * 60)// 1分後にmyFunctinを実行する
    .create();
}

function myFunction() {
  console.log("myFunctionが実行されました。");
  deleteTrigger("myFunction");// トリガーを削除する
}

function deleteTrigger(functionName) {
  const allTriggers = ScriptApp.getProjectTriggers();
  for (let i = 0; i < allTriggers.length; i++) {
    if (allTriggers[i].getHandlerFunction() == functionName) {
      ScriptApp.deleteTrigger(allTriggers[i]);
      console.log("deleteTriggerを実行して、myFunctionのトリガーを削除しました。");
      break;
    }
  }
}




setTriggerを実行すると


myFunctionが登録されます。
このトリガーが実行されるのは
after(1000 * 60)
で設定したミリ秒後です。


そして
myFunctionが実行されると
deleteTrigger("myFunction");
が実行されて
トリガーから削除されます。





2021年2月24日水曜日

VLOOKUP関数の代わりにQUERY関数を使ってみる


Googleスプレッドシートにはクエリ言語を使用して検索できるQUERY関数があります。

本投稿では、普段VLOOKUP関数でやっていることを
QUERY関数でもできそうだったので試してみました。



今回書いた関数
=QUERY(A:B,"select B where A = '"&D2&"' limit 1")



こういうことがしたい

E2に検索結果を返す
  1. D2の値に一致するものを
  2. A列の中から探して
  3. B列の値を返す
  4. 複数結果がある場合は最初に見つかったものだけ返す

今回書いた関数
=QUERY(A:B,"select B where A = '"&D2&"' limit 1")

関数の意訳
QUERY:クエリ言語を使用して、データ全体に対するクエリを実行
A:B:検索範囲
select B:B列の値を返す
where A:A列内で検索する
D2:D2の値に一致するものを探す
limit 1:最初に見つかった結果を返す


複数結果を返したい場合
左側を検索したい場合


参考

VLOOKUP関数では左側を検索できないのでQUERY関数でやってみる


Googleスプレッドシートでは

VLOOKUP関数の範囲指定は
検索キーの右側で
左側にあるデータは参照できない(と思います)

QUERY関数を使うと
左右どちらでも参照できるようになるため
今回その関数を書いてみました。



今回書いた関数
=QUERY(A:B,"select A where B = '"&D2&"' limit 1")



こういうことがしたい

E2に検索結果を返す
  1. D2の値に一致するものを
  2. B列の中から探して
  3. A列の値を返す
  4. 複数結果がある場合は最初に見つかったものだけ返す

今回書いた関数
=QUERY(A:B,"select A where B = '"&D2&"' limit 1")

関数の意訳
QUERY:クエリ言語を使用して、データ全体に対するクエリを実行
A:B:検索範囲
select A:A列の値を返す
where B:B列内で検索する
D2:D2の値に一致するものを探す
limit 1:最初に見つかった結果を返す


複数結果を返したい場合

参考

VLOOKUP関数だけではできない複数結果の取得をQUERY関数でやってみる


Goolgeスプレッドシートでは

一致するキーが複数ある場合、VLOOKUP関数では最初に見つかった結果を返します。

本投稿では一致するすべての結果を返したくて、QUERY関数を使ってみました。



課題
VLOOKUP関数では一致する最初に見つかった結果だけを返す

解決策
QUERY関数で一致するすべての結果を返す



こういうことがしたい

E2に検索結果を返す
  1. D2の値に一致するものを
  2. B列の中から探して
  3. A列の値を返す
  4. 複数結果がある場合は改行を入れる

今回書いた関数
=JOIN(char(10),QUERY(A:B,"select A where B = '"&D2&"'"))


関数の意訳
JOIN:指定した区切り文字を使用して1次元配列の要素を結合
char(10):セルの中で改行する(今回はこれを区切り文字にする)
QUERY:クエリ言語を使用して、データ全体に対するクエリを実行
A:B:検索範囲
select A:A列の値を返す
where B:B列内で検索する
D2:D2の値に一致するものを探す


参考


JOIN

Merge cells with Join formula and CHAR(10)

QUERY syntax using cell reference

2021年2月21日日曜日

Googleドライブのファイルやフォルダのショートカットを作りたい createShortcut(targetId)


createShortcut(targetId)というメソッドができていたので試してみました。


以下のメソッドは廃止されたようです。
 addFile(child) 
 addFolder(child) 
 removeFile(child)
 removeFolder(child) 


Deprecated methods
https://developers.google.com/apps-script/reference/drive/folder#deprecated-methods_1


ファイルのショートカットを作りたい

コード.gs
function createShortCut() {
  const fileId = "このファイルIDのショートカットを作る";
  const targetFolderId = "ショートカットを置くフォルダのID";
  
  DriveApp.getFolderById(targetFolderId).createShortcut(fileId);
}


フォルダのショートカットを作りたい

コード2.gs
function createShortCut() {
  const folderId = "このフォルダIDのショートカットを作る";
  const parentFolderId = "ショートカットを置くフォルダのID";

  DriveApp.getFolderById(parentFolderId).createShortcut(folderId);
}


参考

createShortcut(targetId) 

GoogleドライブのファイルやフォルダをmoveTo(destination)で移動したい


moveTo(destination)というメソッドができていたので試してみました。

以下のメソッドは廃止されたようです。
 addFile(child) 
 addFolder(child) 
 removeFile(child)
 removeFolder(child) 

Deprecated methods
https://developers.google.com/apps-script/reference/drive/folder#deprecated-methods_1


ファイルを移動したい

コード.gs
function moveFile() {
  const fileId = "移動したいファイルID";
  const destinationFolderId = "移動先のフォルダID";
  
  const file = DriveApp.getFileById(fileId);
  const destinationFolder = DriveApp.getFolderById(destinationFolderId);
  
  file.moveTo(destinationFolder);
}


フォルダを移動したい

コード2.gs
function moveFolder() {
  const folderId = "移動したいフォルダのID";
  const destinationFolderId = "移動先のフォルダID";
  
  const folder = DriveApp.getFileById(folderId);
  const destinationFolder = DriveApp.getFolderById(destinationFolderId);
  
  folder.moveTo(destinationFolder);
}


参考

moveTo(destination) 

Deprecated methods

Release Notes
July 27, 2020

2021年2月19日金曜日

Googleドライブの親フォルダ内の子フォルダのファイルを取得してHtmlServiceのselectに入れたい2(テキスト出力する)


先に書いた以下の続きです


Googleドライブのフォルダ構成

親フォルダ
└TEST3
└TEST2
└TEST1
    └サンプル2
    └サンプル1
        └テキスト(ドキュメントのbody)
        └説明(ファイルの説明)


サンプル1の中身


HtmlServiceでこのように表示したい




コード.gs
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index");
}

/************************************
getFoldersInFolder
************************************/
function getFoldersInFolder() {
  const folderId = "親フォルダID";
  const parentFolder = DriveApp.getFolderById(folderId);
  const folders = parentFolder.getFolders();
  let objs = [];
  while(folders.hasNext()) {
    const folder = folders.next();
    const obj = {};
    obj["name"] = folder.getName();
    obj["id"] = folder.getId();
    objs.push(obj);
  }
  return objs;
}

/************************************
getFilesInFolder
************************************/
function getFilesInFolder(folderId) {
  const parentFolder = DriveApp.getFolderById(folderId);
  const files = parentFolder.getFiles();
  let objs = [];
  while(files.hasNext()) {
    const file = files.next();
    const obj = {};
    obj["name"] = file.getName();
    obj["id"] = file.getId();
    objs.push(obj);
  }
  return objs;
}

/************************************
getDataInFile
************************************/
function getDataInFile(fileId) {
  const file = DriveApp.getFileById(fileId);
  const obj = {};
  obj["name"] = file.getName();
  obj["id"] = file.getId();
  obj["description"] = file.getDescription();
  obj["text"] = getDocText(fileId)
  return obj;
}

/************************************
getDocText
************************************/
function getDocText(fileId) {
  const doc = DocumentApp.openById(fileId);
  const body = doc.getBody().getText();
  return body;
}




index.html
<!DOCTYPE html>
<html>
<body>
<div id="main">
  <select id="folders_select"></select>
  <br>
  <select id="files_select"></select>
  <br>
  <textarea id="text"></textarea>
  <textarea id="description"></textarea>
</div>
<script>

elem("folders_select").onchange = selectFolderChanged;
elem("files_select").onchange = selectFileChanged;

get_data();

/************************************
get_data()
************************************/
function get_data() {
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccess)
  .getFoldersInFolder();
}

/************************************
onSuccess(result)
************************************/
function onSuccess(folders) {
  const select = elem("folders_select");
  for(let i = 0; i < folders.length; i++) {
    const name = folders[i]["name"];
    const id = folders[i]["id"];
    console.log(name, id)
    createSelectOptions(select, name, id);
  }
}

/************************************
createSelectOptions
************************************/
function createSelectOptions(select, name, id) {
  const option = document.createElement("option");
  option.textContent = name;
  option.setAttribute("id", id);
  select.appendChild(option);
}

/************************************
selectFolderChanged
************************************/
function selectFolderChanged() {
  const select = elem("folders_select");
  const index = select.selectedIndex;
  const id = select[index].id;
  
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccessFolderChanged)
  .getFilesInFolder(id);
}

/************************************
selectFolderChanged
************************************/
function selectFileChanged() {
  const select = elem("files_select");
  const index = select.selectedIndex;
  const id = select[index].id;
  
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccessFileChanged)
  .getDataInFile(id);
}

/************************************
onSuccessFolderChanged
************************************/
function onSuccessFolderChanged(files) {
  const select = elem("files_select");
  for(let i = 0; i < files.length; i++) {
    const name = files[i]["name"];
    const id = files[i]["id"];
    console.log(name, id)
    createSelectOptions(select, name, id);
  }
}

/************************************
onSuccessFileChanged
************************************/
function onSuccessFileChanged(data) {
  console.log(data);
  elem("text").value = data["text"];
  elem("description").value = data["description"];
}

/************************************
onFailure(e)
************************************/
function onFailure(e) {
  alert([e.message, e.stack]);
}

/************************************
elem(id)
************************************/
function elem(id) {
  return document.getElementById(id);
}

</script>
</body>
</html>




2021年2月18日木曜日

Googleドライブの親フォルダ内の子フォルダのファイルを取得してHtmlServiceのselectに入れたい


先に書いた
Googleドライブの特定フォルダ内のフォルダをHtmlServiceでselectのoptionに追加したい
ではselect要素にoption要素を追加しました。

今回は
optionの選択を変更した時に反応する処理を作ります。

ここでは
Googleドライブの親フォルダ内の子フォルダのファイルを取得して
2つ目のselectにoptionを追加します。


Googleドライブ内のフォルダとファイル

親フォルダ
└TEST3
└TEST2
└TEST1
    └サンプル2
    └サンプル1



HtmlServiceで、2つのselectのoptionの値を操作したい。



コード.gs
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index");
}

/************************************
getFoldersInFolder
************************************/
function getFoldersInFolder() {
  const folderId = "親フォルダのID";
  const parentFolder = DriveApp.getFolderById(folderId);
  const folders = parentFolder.getFolders();
  let objs = [];
  while(folders.hasNext()) {
    const folder = folders.next();
    var obj = {};
    obj["name"] = folder.getName();
    obj["id"] = folder.getId();
    objs.push(obj);
  }
  return objs;
}

/************************************
getFilesInFolder
************************************/
function getFilesInFolder(folderId) {
  const parentFolder = DriveApp.getFolderById(folderId);
  const files = parentFolder.getFiles();
  let objs = [];
  while(files.hasNext()) {
    const file = files.next();
    var obj = {};
    obj["name"] = file.getName();
    obj["id"] = file.getId();
    objs.push(obj);
  }
  return objs;
}



index.html
<!DOCTYPE html>
<html>
<body>
<div id="main">
  <select id="folders_select"></select>
  <br>
  <select id="files_select"></select>
</div>
<script>

elem("folders_select").onchange = selectChanged;

get_data();

/************************************
get_data()
************************************/
function get_data() {
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccess)
  .getFoldersInFolder();
}

/************************************
onSuccess(result)
************************************/
function onSuccess(folders) {
  const select = elem("folders_select");
  for(let i = 0; i < folders.length; i++) {
    const name = folders[i]["name"];
    const id = folders[i]["id"];
    console.log(name, id)
    createSelectOptions(select, name, id);
  }
}

/************************************
createSelectOptions
************************************/
function createSelectOptions(select, name, id) {
  const option = document.createElement("option");
  option.textContent = name;
  option.setAttribute("id", id);
  select.appendChild(option);
}

/************************************
selectChanged
************************************/
function selectChanged() {
  const select = elem("folders_select");
  const index = select.selectedIndex;
  const id = select[index].id;
  
  google.script.run
  .withFailureHandler(onFailure)
  .withSuccessHandler(onSuccessChanged)
  .getFilesInFolder(id);
}

/************************************
onSuccessChanged
************************************/
function onSuccessChanged(files) {
  const select = elem("files_select");
  for(let i = 0; i < files.length; i++) {
    const name = files[i]["name"];
    const id = files[i]["id"];
    console.log(name, id)
    createSelectOptions(select, name, id);
  }
}

/************************************
onFailure(e)
************************************/
function onFailure(e) {
  alert([e.message, e.stack]);
}

/************************************
elem(id)
************************************/
function elem(id) {
  return document.getElementById(id);
}

</script>
</body>
</html>




Googleドライブの特定フォルダ内のフォルダをHtmlServiceでselectのoptionに追加したい


実現したいこと


Googleドライブ内で
以下のように
フォルダの中にフォルダがあって

親フォルダ
└TEST3
└TEST2
└TEST1

その子フォルダを

HtmlServiceの select > option に入れたい。



コード.gs
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index");
}

/************************************
getFoldersInFolder
************************************/
function getFoldersInFolder() {
  const folderId = "親フォルダのID";
  const parentFolder = DriveApp.getFolderById(folderId);
  const folders = parentFolder.getFolders();
  let objs = [];
  while(folders.hasNext()) {
    const folder = folders.next();
    var obj = {};
    obj["name"] = folder.getName();
    obj["id"] = folder.getId();
    objs.push(obj);
  }
  return objs;
}



index.html
function doGet(e) {
  return HtmlService.createHtmlOutputFromFile("index");
}

/************************************
getFoldersInFolder
************************************/
function getFoldersInFolder() {
  const folderId = "16H_yu5VcqSaEy4EHhod0HrPOuGnud233";
  const parentFolder = DriveApp.getFolderById(folderId);
  const folders = parentFolder.getFolders();
  let objs = [];
  while(folders.hasNext()) {
    const folder = folders.next();
    var obj = {};
    obj["name"] = folder.getName();
    obj["id"] = folder.getId();
    objs.push(obj);
  }
  return objs;
}



Googleドライブ内の特定フォルダ内のフォルダ名とidを取得したい


Googleドライブ内で
指定した親フォルダ内の
子フォルダの名前とIDを取得するコードの例です。



コード.gs
function getFoldersInFolder() {
  const folderId = "親フォルダのID";
  const parentFolder = DriveApp.getFolderById(folderId);
  const folders = parentFolder.getFolders();
  let array = [];
  while(folders.hasNext()) {
    const folder = folders.next();
    var obj = {};
    obj["name"] = folder.getName();
    obj["id"] = folder.id();
    array.push(obj);
  }
  Logger.log(array);
}



2021年2月13日土曜日

MacBookのSiriを無効にしたい


最近突然Siriが喋り出すことが複数回ありました。

そんなSiriを無効にしようと試みた備忘録です。

OS:Catalina


やったこと
システム環境設定 > Siri > ”Siriに頼む”のチェックを外す


STEP


STEP1
左上のメニューから「システム環境設定」を開きます


STEP2
「Siri」をクリックします


STEP3
”Siriに頼む”を有効にするにチェックが入っている

クリックしてチェックを外します


これで勝手に喋り出さなくなってほしい。


参考

MacのSiri環境設定を変更する
https://support.apple.com/ja-jp/guide/mac-help/mchl3fd7fc15/mac

MacでSiriを使用する

2021年2月10日水曜日

Slackbotでランダム返信させたい(コードを書かずに)


コードを書かずにSlackの機能でできました。



Preferencesの中にカスタマイズメニューがあります。
(階層や名称は環境によって異なるかも)


以下のURLのNAME部分を
自分の環境のものにしてアクセスすると設定画面が開くはず。
https://NAME.slack.com/customize/slackbot


STEP

Preferences > Customize



Slackbotを選択して
Add New Responseをクリックします。


When someone says:なんて言ったら
Slackbot responds:なんて返す(複数入れるとどれか一つを返すらしい)
を決めてSaveをクリックします。


試してみます。

2021年2月9日火曜日

スクリプトのプロパティをコードで削除したい


Google Apps Scriptの旧UIでプロパティを削除できなかったのでコードでやってみる。



スクリプトのプロパティの右端にある「削除」をクリック→保存しても削除されなかった。




これで削除できました。

コード.gs
function deleteProperty() {
  var key = "foobar";// 削除したいプロパティのキーを指定
  PropertiesService.getScriptProperties().deleteProperty(key);
}


補足

新UIではそもそもプロパティを表示する画面がみつからない。
これからはコードで読み書きしていくことになりそうだ。

2021年2月7日日曜日

正規表現でAND検索を試してみる3


のパターンを動的に作る方法を分解したコード。

"文字列1", "文字列2"を配列で渡して

こういう結果を得たくて書いたコードです。
 ^(?=.*文字列1)(?=.*文字列2)



コード.gs
function myFunction() {
  var values = ["文字列1", "文字列2"];
  var pattern = createAndSearchPattern(values);
  Logger.log(pattern);
}

function createAndSearchPattern(values) {
  var pattern = "^";
  for(var i = 0; i < values.length; i++) {
    pattern += "(?=.*" + values[i] + ")";
  }
  return pattern;
}



2021年1月30日土曜日

スプレッドシートの改行をHtmlServiceで表現したい value.replace(/\n/g, "<br>")


セル内の改行は "\n"
それをHTML側で "<br>" に置き換えます。

複数の改行へ対応できるようにgを加えて

value.replace(/\n/g, "<br>");

(valueはシートから取得したセルの値)

手元ではこれで実現できました。


やってみる

STEP1
A1セルに
あいうえお
かきくけこ
さしすせそ
という値を入れておきます。


STEP2
セルの改行を<br>に置き換えないとこうなります。
あいうえお かきくけこ


STEP3
セルの改行を<br>に置き換えるとこうなります。
あいうえお
かきくけこ
さしすせそ




コード.gs
function doGet() {
  return HtmlService.createHtmlOutputFromFile("index");
}

function returnA1() {
  const sheet = SpreadsheetApp.getActiveSheet();
  const A1Value = sheet.getRange("A1").getValue();
  return A1Value;
}

意訳
この機能がやること
指定したHTMLファイルを表示する


この機能がやること
スプレッドシートを取得して
A1の値を取得して
返す





index.html
<!DOCTYPE html>
<html>
  <body>
    <div id=main></div>
    <script>
      load();
      function load() {
        google.script.run
        .withFailureHandler(onFailure)
        .withSuccessHandler(onSuccess)
        .returnA1();
      }

      function onSuccess(value) {
        const text = value.replace(/\n/g, "<br>");
        document.getElementById("main").innerHTML = text;
      }

      function onFailure(e) {
        console.log([e.message, e.stack]);
      }
    </script>
  </body>
</html>
意訳
 
 
 
 
 
load()を実行する
この機能がやること
.gsファイルのreturnA1()を実行する
失敗したらonFailureを実行する
成功したらonSuccessを実行する



この機能がやること
渡されたvalueの\nを全部に置き換えて
指定したidの要素へHTML形式で入れる


この機能がやること
コンソールログにエラーメッセージを出す







2021年1月24日日曜日

JIRAで組織管理者を追加したい


JIRAで組織の管理者を追加したときの備忘録です。


以下の手順で追加できました。


STEP1
「JIRA組織管理者追加」でググってみます。


STEP2
ユーザに管理者権限を与える」がそれっぽいので開いてみます。


STEP3
ページに記載されている「ユーザーを組織管理者にする方法」の手順を実行します。

まずは、以下のリンクから組織にログインします。


STEP4
環境に応じた組織名が表示されるので、対象の組織名をクリックします。


STEP5
上部メニューの右端にある「設定」をクリックします。


STEP6
左部メニューの「Administrators」をクリックします。


STEP7
右端の「Add administrators」をクリックします。


STEP8
追加したいメールアドレスを入れて「Grant access」をクリックします。


手元の環境では、以上で組織の管理者が追加できました。


参考

ユーザーに管理者権限を付与する

2021年1月17日日曜日

Google Apps ScriptのHtmlServiceでサーバーエラーが頻発する


最近HtmlServiceでWebアプリを開発中に、サーバーエラーが頻繁に発生するなぁ

と思って調べてみたら

すでにissueがあがっていました。


500 error when refreshing script dev

まだAssigneeはついていない様子(2021/01/17現在)


デプロイして/execで開くとうまくいくとかいかないとか...
スターを付けておくとissueの更新がメールで届くのでクリックしておきました。



ちなみに手元ではこんな感じでエラーが表示されました。

日本語
サーバー エラーが発生しました。しばらくしてからもう一度試してください。

英語
We're sorry, a server error occurred. Please wait a bit and try again.

(上記以外でも、withFailureHandlerでエラーが返ってくる場合もある)

最新の投稿

マイドライブを指定してファイルを保存したい(DriveApp.getRootFolder())

以前書いた CSVデータを作ってGoogleドライブに保存する では、特定のフォルダを指定して保存しました。 ここでは「マイドライブ」に保存するコードを書きました。 save_as_csv()を実行すると マイドライブにvar dataで設定したデータが保存されて そのファイル...