ふーログhttps://www.fulogabc.netガジェット・アニメ・ときどきアウトドアWed, 24 Dec 2025 21:46:30 +0000jahourly1SharePointリストの情報を可視化・出力するPower AppsとPower Automateの構成https://www.fulogabc.net/entry/sharepoint-list-visualize-export-powerapps-powerautomatehttps://www.fulogabc.net/entry/sharepoint-list-visualize-export-powerapps-powerautomate#respondWed, 24 Dec 2025 15:23:43 +0000https://www.fulogabc.net/?p=3693

この記事は、Power Apps Advent Calendar 2025 12月25日 担当分の記事です。 仕事でよくSharePointリストを活用していますが、長く使っているとこんな悩みが出てきます。 ShareP ... ]]>

この記事は、Power Apps Advent Calendar 2025 12月25日 担当分の記事です。

仕事でよくSharePointリストを活用していますが、長く使っているとこんな悩みが出てきます。

  • 列が増えすぎて、フォームやビューがごちゃごちゃしてきた
  • 一時的に非表示にしていたリストを、また表示したくなった
  • どのリストが「非表示(Hidden)」になっているのかパッと分からない
  • 設計見直しのために、列情報をExcelで一覧にしたい

SharePointの機能でも出力や確認はできますが、

  • 画面を何度も行き来する
  • リストを一つずつクリックして確認する

…という地味に面倒な作業になりがちです。

そこでこの記事では、

  • SharePointリストの情報を取得して一覧表示
  • 選択したリストについて、Hidden を true/false に切り替えて表示/非表示を変更
  • さらに、列情報をExcelにそのまま貼り付けできる形式でコピー

できる Power Apps + Power Automate の構成を紹介します。

アプリ・フローのダウンロード

アプリとフローはGitHubに公開しています。下記URLからダウンロードしてご利用いただけます。

完成イメージ

完成すると、だいたいこんなことができます。

  1. サイトURLを指定して「リスト取得」ボタンを押す
  2. そのサイトに存在するリストが、ギャラリーに一覧表示される

表示内容
  1. フォルダかリストか(BaseType)
  2. 表示名(Title)
  3. ドメイン以降のURL(ServerRelativeUrl)
    ※選択するとSharePointリストへ移動
  4. Id(Id)
  5. リストの説明文(Description)
  6. 表示/非表示(Hidden)
    ※ボタンから切り替えが可能

  1. 「詳細を表示」ボタンを押す
  2. そのリスト存在する列が、ギャラリーに一覧表示される
  3. 「Excelにコピー」ボタンを押すと、列情報がタブ区切りテキストでクリップボードに入り、そのまま Excel に貼り付けできる。

これのアプリを使うことで、

  • リスト設計書
  • Power Apps フォームの設計表
  • 移行/棚卸しのための一覧

などを、すぐにExcelで作成できます。

では、細かい部分を解説していきます。

全体構成・機能

だいたいこのような構成・機能です。

  1. Power Automate
    1. SharePoint REST API を叩いて、サイトのリスト一覧を取得するフロー。
    2. SharePoint REST API を叩いて、リストのHiddenを更新するフロー。
    3. SharePoint REST API を叩いて、リストの列(フィールド)情報を取得するフロー。
  2. Power Apps(キャンバスアプリ)
    1. 画面上からフローを呼び出して JSON を受け取る
    2. 画面上からフローを呼び出してHiddenを更新する
    3. ParseJSON() でコレクションに展開
    4. テーブル情報をクリップボードへ貼り付ける

SharePoint REST API を叩いて、サイトのリスト一覧を取得するフロー

サイトの一覧を取得するフローは下記の通りです。

「SharePoint に HTTP 要求を送信します」に下記URIを指定します。

_api/web/Lists?$select=Title,Hidden,Description,Id,BaseType&$expand=RootFolder&$filter=(substringof('thread.skype_wiki',Title) eq false)and(IsCatalog eq false)

_api/web/Lists

ここは「Web(サイト)の中にある 全てのリスト/ライブラリのコレクション」に対するアクセスです。

  • List オブジェクト(SharePointのリスト/ライブラリ)が返ってきます。
  • ここから $select / $filter で絞り込みをしていきます。

$select=... の意味

$select=Title,Hidden,Description,Id,BaseType

TitleやDescriptionなど必要な列のみを選択して取得しています。他の取得できる列は下記の通り。必要に応じて追加等できます。

プロパティ名型 / 例意味・役割(日本語解説)
AllowContentTypestrueこのリストでコンテンツ タイプ(Content Type)を使えるかどうか。true なら複数のコンテンツ タイプを関連付け可能。
BaseTemplate100リストのテンプレート種別を示す番号。100 は「カスタム リスト」。タスクリストやライブラリなどは別の番号。
BaseType0リストの基本タイプ。0 = 通常のリスト、1 = ドキュメント ライブラリ、など。
ContentTypesEnabledfalseコンテンツ タイプの管理が有効か。false の場合、UI上でコンテンツタイプの追加/管理ができない状態。
CrawlNonDefaultViewsfalse既定ビュー以外も検索クロールの対象にするか。false だと既定ビュー中心にクロールされる。
Created"2022-10-01T11:16:50Z"リストが作成された日時(UTC)。
CurrentChangeToken.StringValue"1;3;...;48208326"リストの変更トークン。差分取得や変更履歴の追跡に使われる内部的なID。
DefaultContentApprovalWorkflowId"0000..."既定のコンテンツ承認ワークフローのID。全0なので、承認ワークフローは関連付けられていない状態。
DefaultItemOpenUseListSettingfalseアイテムを開くときにブラウザー/クライアントの既定動作を使うかどうかなどの設定。通常はドキュメントライブラリで影響。
Description"testテスト"リストの説明文。SharePoint UIで表示される「説明」。
Direction"none"文字の方向。none / ltr / rtl(左→右 / 右→左)。日本語や英語は通常 noneまたはltr
DisableCommentingfalseアイテムへのコメント機能を無効にするかどうか。false なのでコメント可能。
DisableGridEditingfalseクイック編集(グリッドビューでの編集)を無効にするかどうか。false なのでクイック編集可能。
DraftVersionVisibility0下書きバージョンの閲覧権限。0 は「すべてのユーザー」など、数値でモードが決まる(承認者のみなど)。
EnableAttachmentstrueリストアイテムに添付ファイルを付けられるか。true で添付可能。
EnableFolderCreationfalseリスト内でフォルダーを作成できるか。false なのでフォルダー作成不可。
EnableMinorVersionsfalse下位バージョン(0.1, 0.2…など)を利用するか。通常はドキュメントライブラリで使用。
EnableModerationfalseコンテンツ承認(承認/却下のワークフロー)を有効にするか。
EnableRequestSignOfftrue「承認の依頼」(Sign-off)機能が有効か。UIから簡易承認依頼を送る機能。
EnableVersioningtrueバージョン管理が有効か。true なので変更ごとにバージョン履歴が残る。
EntityTypeName"20221001_x005f_List"リストのエンティティ型名。RESTやPower Appsから参照するときの内部名に近い。
ExemptFromBlockDownloadOfNonViewableFilesfalse「表示のみ可能なファイルのダウンロード制御」から除外するか。IRM/情報保護関連の設定。
FileSavePostProcessingEnabledfalseファイル保存後の追加処理(ポストプロセス)が有効かどうか。主にライブラリ向けの内部設定。
ForceCheckoutfalseファイル編集時にチェックアウトを強制するかどうか。true なら編集前に必ずチェックアウトが必要。
HasExternalDataSourcefalse外部データ ソースと接続されたリストか(外部リスト/BCS)。
Hiddenfalseリストが UI から隠されているかどうか。false なのでサイトコンテンツなどに普通に表示される。
Id"1583..."このリスト自体の GUID。サイト内で一意のID。
ImagePath.DecodedUrl"/_layouts/15/images/itgen.png?rev=47"リストのアイコン画像へのパス(デコード済みURL)。
ImageUrl"/_layouts/15/images/itgen.png?rev=47"同じくリストアイコンのURL。SharePoint標準アイコン。
DefaultSensitivityLabelForLibrary""既定の感度ラベル(Sensitivity Label)。空文字なので未設定。主にM365情報保護機能用。
IrmEnabledfalseInformation Rights Management(IRM)が有効かどうか。
IrmExpirefalseIRMポリシーによる有効期限設定を使うかどうか。
IrmRejectfalseIRMルール違反時にダウンロードなどを拒否するか。
IsApplicationListfalseアプリケーションレベルのリスト(隠しリスト等)かどうか。通常ユーザーが作るリストは false
IsCatalogfalseカタログ用リスト(検索結果やナビゲーションに使う特別なリスト)かどうか。
IsPrivatefalseプライベートリストかどうか(特定ユーザーのみ可視)。false なので基本は公開設定。
ItemCount4リスト内のアイテム数(現在 4 件)。
LastItemDeletedDate"2022-10-01T11:16:50Z"最後にアイテムが削除された日時。
LastItemModifiedDate"2025-11-30T06:02:19Z"最後に「何らかのアイテム」が更新された日時(システム更新含む)。
LastItemUserModifiedDate"2025-11-30T06:02:19Z"最後に「ユーザー操作で」アイテムが更新された日時。
ListExperienceOptions0モダン/クラシックなどリストの表示エクスペリエンスのオプション値。0 はサイト既定に従うなど。
ListItemEntityTypeFullName"SP.Data.20221001_x005f_ListItem"アイテムのフルエンティティ名。REST APIでPOST/GET時の @odata.type に使われる。
MajorVersionLimit50バージョン履歴として保持するメジャーバージョンの最大数。51個目以降は古いものから自動削除。
MajorWithMinorVersionsLimit0メジャー+マイナーバージョンの合計上限。0 の場合は未設定扱い or 下位バージョン無効。
MultipleDataListfalse複数データ ソースを扱う特殊なリストかどうか。通常リストは false
NoCrawlfalseこのリストを検索クロールから除外するかどうか。false なので検索対象。
ParentWebPath.DecodedUrl"/sites/testshp"親サイト(Web)のパス。
ParentWebUrl"/sites/testshp"親サイトのURL。
ParserDisabledfalseドキュメントパーサーを無効にしているか(検索インデックス用の解析など)。
ServerTemplateCanCreateFolderstrueこのテンプレート種別のリストでフォルダーが作成可能かどうか(サーバーテンプレート定義)。
TemplateFeatureId"00bfea71-de22-43b2-a848-c05709900100"リストを作る元になった機能(Feature)の GUID。100(カスタムリスト)に対応。
Title"2022-10-01_メール添付ファイルテスト"リストのタイトル(表示名)。サイトコンテンツなどに表示される名前。

$expand=RootFolderの意味

$expand で関連オブジェクト(RootFolder)を一緒に取得してます。

プロパティ名例 / 型意味・役割(日本語解説)
Existstrueこのフォルダーが実際に存在するかどうか。通常、正常なリストなら true
ExistsAllowThrowForPolicyFailurestrueポリシー違反(保持ポリシーなど)があっても「存在チェック時に例外を投げてもよい」といった内部用フラグ。true なら、実体があれば存在扱い。
ExistsWithExceptiontrue存在確認時に例外が発生する可能性を含めて「存在する」と見なすかどうか。基本的には内部的な状態チェック用。
IsWOPIEnabledfalseWOPI (Office Web Apps / Office Onlineでのブラウザ編集) が有効かどうか。ドキュメントライブラリのルートフォルダで true になることが多いですが、リストでは通常 false
ItemCount4このルートフォルダ直下にあるアイテム数(リストアイテム数 / ファイル数)。ここではリストに 4 件登録されている。
Name"20221001_"フォルダ名。リスト/ライブラリの内部名に相当し、URL パスの一部にもなる。
ProgIDnullCOM 連携などで使うプログラム ID。通常のリスト・フォルダでは null のことがほとんど。
ServerRelativeUrl"/sites/testshp/Lists/20221001_"サイト コレクション ルートからのサーバー相対パス。REST や Web パーツでパス指定するときに使える。例:https://tenant.sharepoint.com + ServerRelativeUrl で完全URLになる。
TimeCreated"2022-10-01T11:16:50Z"このルートフォルダが作成された日時(UTC)。リスト作成日時と同じになる。
TimeLastModified"2025-11-30T15:19:33Z"このフォルダ配下で最後に変更があった日時(アイテム追加・更新・削除など)。
UniqueId"dd691569-8bc5-4a4e-b1a0-3b66684a0fd4"このフォルダの GUID。サイト内で一意な ID。別の API でフォルダを一意に指定するときに使える。
WelcomePage""このフォルダの「ようこそページ」(既定ページ)の相対パス。ドキュメントライブラリなら Forms/AllItems.aspx などが入ることもあるが、このリストでは空。

$filter=... の意味

$filter=(substringof('thread.skype_wiki',Title) eq false)and(IsCatalog eq false)

ここは 取得するリストを条件で絞り込む 部分です。

4-1.substringof('thread.skype_wiki', Title) eq false

  • substringof(A, B)
    → 「文字列 B の中に文字列 A が含まれているか」を判定する関数
  • ここでは
    substringof('thread.skype_wiki', Title)
    → 「Title に ‘thread.skype_wiki’ が含まれているか?」になっています。

eq false なので、

タイトルに 'thread.skype_wiki' を含まないリストだけを取得という意味です。
(Teams/Skype 関連の内部用リストを除外したいため。)


4-2.IsCatalog eq false

IsCatalog は SharePoint List のフラグで、

画像ライブラリやテンプレートギャラリーなどのカタログ的な特別用途のリスト を判定するプロパティです。

IsCatalog eq false なので、カタログ用ではない、通常のリストだけを取得

という条件になります。


4-3.and で両方満たすものだけ

全体では

(substringof('thread.skype_wiki',Title) eq false)
and
(IsCatalog eq false)

なので、

  • タイトルに 'thread.skype_wiki' を含まない
    かつ
  • カタログ用でない

リストだけが返ってきます。

あとは、取得したデータをPowre Appsに渡してコレクションで表示させます。

画面上からフローを呼び出して JSON を受け取る

リストを取得するボタンには下記を設定しています。

ボタン.OnSelect
// --- 基本エラーフラグ(boolean)を設定 -------------------------------
UpdateContext({ _urlError: IsBlank(txt_lext_top_siteURL.Value)
});
// --- エラーコレクションを作って、まとめて通知 or 成功処理 ------------------
ClearCollect( _errorsB, { flag: _urlError, msg: "「サイトURLが入力されていません」" }
);
If( CountRows(Filter(_errorsB, flag)) > 0, // ---- エラーあり:まとめて警告 ---- Notify( "エラーです。確認をお願いします。 " & Concat(Filter(_errorsB, flag), msg & " "), NotificationType.Warning ), // ---- エラーなし:ドメイン取得、Power Automate 実行 → JSON をテーブル化 ---- // ---- loading表示 ---- UpdateContext({loadingVisible: true}); // ---- データ初期化・クリア ---- UpdateContext( { _siteDomain:Blank(), _SPListtmp:Blank(), SPLists:Blank() } ); UpdateContext( { _siteDomain: Mid( txt_lext_top_siteURL.Value, Find("//", txt_lext_top_siteURL.Value) + 2, Find(".sharepoint.com", txt_lext_top_siteURL.Value) - (Find("//", txt_lext_top_siteURL.Value) + 2) ) } ); UpdateContext({_SPListtmp: 'SharePointリスト一覧取得'.Run(txt_lext_top_siteURL.Value)}); UpdateContext( { SPLists: ForAll( Table(ParseJSON(_SPListtmp.reslt)), { Title: Text(ThisRecord.Value.Title), Description: Text(ThisRecord.Value.Description), Id: Text(ThisRecord.Value.Id), Hidden: Boolean(ThisRecord.Value.Hidden), ServerRelativeUrl:Text(ThisRecord.Value.ServerRelativeUrl), BaseType: Value(ThisRecord.Value.BaseType) } ) }
);
// ---- loading非表示 ----
UpdateContext({loadingVisible: false});
);// ---- IF閉じるカッコ ----

それぞれ解説します。

1. 入力チェック用のエラーフラグを設定

UpdateContext({ _urlError: IsBlank(txt_lext_top_siteURL.Value)
});

画面上のテキスト入力 txt_lext_top_siteURL にサイトURLが入っているかをチェックしています。

IsBlank(...)true のときは「未入力」、false のときは「入力あり」です。

  • その結果をコンテキスト変数 _urlError(boolean)に保存。
    • _urlError = true → エラーあり(サイトURLが空)
    • _urlError = false → エラーなし

今後エラーチェックを増やしたいときにこのフラグを追加していくだけで良く、拡張しやすい構成です。

2. エラー情報をコレクションにまとめる

ClearCollect( _errorsB, { flag: _urlError, msg: "「サイトURLが入力されていません」" }
);

_errorsB というコレクションに、エラー情報を1行として格納しています。

  • 各行は { flag: <エラーフラグ>, msg: "<ユーザーに見せるメッセージ>" } という構造。

今は1件だけですが、今後エラー判定を増やす場合でも、このコレクションにレコードを追加するだけで済むようになっています。

3. エラーがあるかどうかで処理を分岐

If( CountRows(Filter(_errorsB, flag)) > 0, // エラーあり:まとめて通知 Notify( "エラーです。確認をお願いします。 " & Concat(Filter(_errorsB, flag), msg & " "), NotificationType.Warning ), // エラーなし:後続処理(REST呼び出しなど) ...
);
  • Filter(_errorsB, flag)
    flag = true のレコードだけを抽出(=本当にエラーになっている項目)。
  • CountRows(...) > 0 なら、1件以上エラーがある、という判断です。

エラーがある場合は、

  • Notify() で警告を出し、
  • Concat(Filter(_errorsB, flag), msg & " ") で、エラー行に紐づく msgまとめて連結して表示しています。

将来的にエラー項目を増やしても、この書き方ならメッセージを自動で全部つなげてくれます。非常に便利です。

4. エラーがない場合の処理:ローディング表示・初期化・REST呼び出し

If の 「第2引数」側 が、「エラーがないときに実行する一連の処理」です。

4-1. ローディング表示ON

UpdateContext({loadingVisible: true});

画面上のローディングオーバーレイ用に、loadingVisible フラグを立てています。

これを元に、コンテナの Visible に紐づけています。

4-2. 一旦、関連変数をクリア

UpdateContext( { _siteDomain: Blank(), _SPListtmp: Blank(), SPLists: Blank() }
);

前回までの処理結果が残っていると紛らわしいので、ドメイン・一時変数・リスト一覧を一度 Blank() にリセットしています。初期化せずとも動きますが、しっかりデータが再取得できているかを分かりやすくするために行っています。

4-3. サイトURLからドメイン部分を抜き出す

UpdateContext(
{ _siteDomain: Mid( txt_lext_top_siteURL.Value, Find("//", txt_lext_top_siteURL.Value) + 2, Find(".sharepoint.com", txt_lext_top_siteURL.Value) - (Find("//", txt_lext_top_siteURL.Value) + 2) )
}
);

後で REST API のURLを組み立てるときなどに使うため、テナント名だけ抜き出しています

  • txt_lext_top_siteURL.Value 例:
    https://xxx.sharepoint.com/sites/hoge
  • Find("//", ...) + 2
    https://// のすぐ後ろ(= xxx.sharepoint.com... の先頭)
  • Find(".sharepoint.com", ...)
    .sharepoint.com の位置
  • Mid( 文字列, 開始位置, 文字数 ) を使って、
    xxx の部分(=テナント名)を切り出し、_siteDomain として保存しています。

4-4. Power Automate フローを実行して SharePoint リスト一覧を取得

UpdateContext({_SPListtmp: 'SharePointリスト一覧取得'.Run(txt_lext_top_siteURL.Value)});

Power Automateのフローを実行して、ローの戻り値を _SPListtmp というコンテキスト変数に保持しています。

4-5. 返ってきたJSONを ParseJSON → テーブル化

UpdateContext(
{
SPLists: ForAll(
Table(ParseJSON(_SPListtmp.reslt)),
{
Title: Text(ThisRecord.Value.Title),
Description: Text(ThisRecord.Value.Description),
Id: Text(ThisRecord.Value.Id),
Hidden: Boolean(ThisRecord.Value.Hidden),
ServerRelativeUrl: Text(ThisRecord.Value.ServerRelativeUrl),
BaseType: Value(ThisRecord.Value.BaseType)
}
)
}
);
  • _SPListtmp.reslt
    → フローから返ってきた SharePoint リスト一覧のJSON文字列。
  • Table(ParseJSON(...))
    → JSON配列を Power Fx で扱える「テーブル(レコードの集合)」に変換。
  • ForAll(...) の中で、
    各レコード (ThisRecord.Value) から必要な項目を取り出し、
    型を Text / Boolean / Value に整えた上で、
    新しいテーブル SPLists を作成しています。

これにより、SPLists は:

TitleDescriptionIdHiddenServerRelativeUrlBaseType

といった構造のテーブル(コレクション)として扱えるようになり、ギャラリーやテーブルコントロールにそのままバインドできます。

5. 最後にローディング表示をOFF

UpdateContext({loadingVisible: false});
  • 一通りの処理(REST呼び出し → JSON解析 → SPLists 作成)が終わったら、最初に ON にした loadingVisiblefalse に戻します。
  • これでローディング中の表示が消え、取得したリストの一覧が画面に表示されます。

SharePoint REST API を叩いて、リストのHiddenを更新するフロー

URI

_api/web/lists(guid'{リストGUID}')

URIには上記を設定します。GUIDを使って特定します。(タイトル名ではない)

ヘッダー

{
"Accept": "application/json;odata=verbose",
"Content-Type": "application/json;odata=verbose",
"IF-MATCH": "*",
"X-HTTP-Method": "MERGE"
}

ここでは、REST API を 「既存リストの更新(MERGE)」 として呼び出すための設定をしています。

  • X-HTTP-Method: "MERGE"
    → 実際には MERGE(部分更新)として扱ってほしい という合図
  • IF-MATCH: "*"
    → ETag(バージョン)を問わず更新を許可する指定
    (厳密な競合チェックをせず、「とにかく上書きOK」という挙動になります)
  • Accept / Content-Type
    application/json;odata=verbose で、「JSON(OData verbose 形式)で送受信する」ことを示しています。

body:更新するプロパティ

{
"__metadata": {
"type": "SP.List"
},
"Hidden": "{true/false}",
"Title": "{リストのタイトル(表示名)}",
"Description": "{リストの説明}"
}

__metadata.type

"__metadata": { "type": "SP.List"
}

SharePoint の REST API では、更新(POST / MERGE)をするときに上記のような形で 「これは何の型のオブジェクトか」 を明示する必要があります。

  • OData 的には「エンティティの型情報」
  • SharePoint 的には「SP.List / SP.ListItem / SP.File などどのクラスを更新するか」を示すもの

これが一致していないと、

  • 更新時にエラーになったり
  • 無視されたり

するので、REST 経由で更新するときはほぼ必須の指定です。

よく使う __metadata.type の例

代表的なものだけ抜き出すとこんな感じです。

対象__metadata.type の例
サイトコレクションのリスト(リスト定義)SP.List
通常のリストアイテムSP.ListItem
ドキュメントライブラリのファイルSP.File
フォルダーSP.Folder
コンテンツタイプSP.ContentType

リストとドキュメントライブラリは、両方とも「リスト定義」としては SP.List です。今回のアプリではこの2つのみ扱うため、メソッドは固定で問題ありません。

Hidden

"Hidden": "{true/false}",

リスト自体を 隠しリストにするかどうか を表すプロパティです。

  • true → 隠しリスト(UIに出さない)
  • false → 通常のリスト

フローのトリガーから boolean という名前で真偽値(または “true”/”false” 文字列)を受け取り、そのまま反映しています。

→ Power Appsのボタンで、!ThisItem.Hiddenと記述し、現在の状態の逆の値をフローへ渡すようにしています。

タイトル等も更新できるようにBodyに書いていますが、このアプリ画面上では変更ができないようにしていますので、何も変更されません。使いたい方はアプリを編集してご利用ください。

SharePoint REST API を叩いて、URLを変更するフロー

こちらは技術的には可能で設定だけしましたが、アプリでは使ってません。使いたい方はアプリ等を変更して使えると思います。

_api/web/lists(guid'{リストGUID}')/RootFolder/MoveTo(newurl='/sites/testshp/Lists/◯◯◯◯')

前半:対象リスト

_api/web/lists(guid'◯◯◯◯')

GUID が ◯◯◯◯ のリストを取得
→ どのリストかは GUID で特定している(タイトル名ではない)

中盤:RootFolder

/RootFolder

そのリストの「ルートフォルダー」(実体のフォルダー)を指しています

例:/sites/testshp/Lists/今のURL名

後半:MoveTo(newurl=…)

/MoveTo(newurl='/sites/testshp/Lists/list004')

機能としては、

  • Folder.MoveTo メソッドを呼び出し
  • newurl に指定したパスへフォルダーを移動する(=URLを変える)

結果として:

リストの RootFolder を /sites/testshp/Lists/list004 に移動(URL 名を list004 に変更)する

という処理になります。
見た目の「タイトル」はそのままで、「リストのURL名」だけを変えることができます。

SharePoint REST API を叩いて、ターゲットリストの列(フィールド)情報を取得するフロー

SharePoint REST API のURI解説(フィールド情報取得)

Power Automate から SharePointリストの列情報(フィールド情報)を取得するために、次の REST API を呼び出しています。

_api/web/lists(guid'@{triggerBody()?['text_1']}')/Fields?$filter=Hidden eq false&$select=Title,InternalName,TypeDisplayName,TypeAsString,Required,ReadOnlyField,CanBeDeleted

このURIが何をしているのか、順番に分解して解説します。

1. 対象リストの指定部分

_api/web/lists(guid'@{triggerBody()?['text_1']}')/Fields

_api/web/lists(...)

  • _api/web
    → 現在のサイトコレクション(Web)を表すエンドポイントです。
  • lists(guid'...')
    → GUID(ID)で特定のリストを指定しています。

guid'@{triggerBody()?['text_1']}'
  • Power Automate の @{triggerBody()?['text_1']} は、トリガーや前のアクションから渡された リストID(GUID) を表す式です。
  • Power Apps から「リストID」をパラメータとしてフローに渡しておき、この値をここに差し込んでいます。

この部分は、
「Power Automate に渡されたリストID(GUID)のリストをREST APIの対象にする」
という意味になります。

/Fields

  • 指定したリストの「Fields(フィールドのコレクション)」にアクセスしています。
  • 1件1件が「列(Title 列、Custom列、システム列など)」の情報です。

2. $filter=Hidden eq false(非表示列を除外)

?$filter=Hidden eq false
  • Hidden プロパティは、その列が 非表示列かどうか を表すフラグです。
    • true → 隠し列(UIに出てこないシステム列などが多い)
    • false → 通常表示される列
  • Hidden eq false なので、
    • 非表示ではない列(Visibleな列)だけを取得する
      というフィルター条件になっています。

このフィルターを入れることで、システム寄りの隠し列を省き、ユーザーが扱う通常の列に絞って情報を取得できます。

3. $select=...(必要なプロパティだけ取得)

$select=Title,InternalName,TypeDisplayName,TypeAsString,Required,ReadOnlyField,CanBeDeleted

ここでは、フィールドの中から必要なプロパティだけを選んで取得しています。

  • Title
    → 列の表示名(SharePointの列設定画面で見る「列名」)
  • InternalName
    → 列の内部名。Power Apps や REST API、クエリなどから参照するときに使う名前です。
  • TypeDisplayName
    → 「単一行テキスト」「選択肢」「数値」など、人間向けの型名称。
  • TypeAsString
    → 内部的な型名(TextChoiceNumberDateTime など)を文字列で表現したもの。
  • ReadOnlyField
    true → 読み取り専用(ユーザーが編集できない)、false → 編集可能
  • CanBeDeleted
    → 削除可能な列かどうか。システム列など削除できない列は false になります。

URIとしては、例えば次のような形が正しい指定になります。

まとめ

この REST API は、一言でいうと:

「トリガーから渡されたリストIDのリストについて、Hidden ではない(表示対象の)列だけを対象に、列名・内部名・型・必須/読み取り専用/削除可否などの情報を取得する」

ためのURIになっています。

この結果を Power Automate → Power Apps に返し、ParseJSON()ForAll() で展開することで、

  • 設計一覧の表示
  • Excelへのコピー
  • 列の Hidden 切り替え画面の補助情報

などに活用できる、という流れになります。

テーブル情報をExcelに貼り付ける形式にする

Power Apps で取得した SharePoint列情報(_SPFields コレクション)を、
Excel にそのまま貼り付けられるテキスト に組み立てて、クリップボードにコピーする部分を解説します。

仕組みは簡単で変数にタブ区切りで結合しているだけです。

Excelコピーボタン.OnSelect
// --- ヘッダー+明細をタブ区切り&改行のテキストにする -------------------------------
Set( varClipboardText, // --- ヘッダー行 --- "Title" & Char(9) & "InternalName" & Char(9) & "TypeDisplayName" & Char(9) & "TypeAsString" & Char(9) & "Required" & Char(9) & "CanBeDeleted" & Char(9) & "ReadOnlyField" & Char(10) & // --- 明細行 --- Concat( _SPFields, Text(Title) & Char(9) & Text(InternalName) & Char(9) & Text(TypeDisplayName) & Char(9) & Text(TypeAsString) & Char(9) & If(Required, "TRUE", "FALSE") & Char(9) & If(CanBeDeleted, "TRUE", "FALSE") & Char(9) & If(ReadOnlyField, "TRUE", "FALSE") & Char(10) )
);
// --- クリップボードにコピー -------------------------------
Copy(varClipboardText);
Notify("クリップボードにコピーしました。")

1. ヘッダー+明細を 1 本のテキストに組み立てる

Set( varClipboardText, ...
);

まず Set() で、Excel貼り付け用のテキストを varClipboardText という変数 に作っています。

中身は大きく分けて 2 部分です。

  • ヘッダー行
  • 明細行(_SPFields の各レコード)

2. ヘッダー行の作成

// --- ヘッダー行 ---
"Title" & Char(9) &
"InternalName" & Char(9) &
"TypeDisplayName" & Char(9) &
"TypeAsString" & Char(9) &
"Required" & Char(9) &
"CanBeDeleted" & Char(9) &
"ReadOnlyField" & Char(10) &
  • "Title""CanBeDeleted" が、Excel の 1行目に表示したい列名 です。
  • Char(9)タブ文字 を表します。
    → Excel に貼ると「次の列」に移動します。
  • 最後の Char(10)改行 です。
    → ここまでが 1 行目(ヘッダー行)になり、その下から明細行が続きます。

結果イメージ(Excel上):

TitleInternalNameTypeDisplayNameRequiredCanBeDeleted

3. 明細行(_SPFields の中身)を Concat で連結

// --- 明細行 ---
Concat(
_SPFields,
Text(Title) & Char(9) &
Text(InternalName) & Char(9) &
Text(TypeDisplayName) & Char(9) &
Text(TypeAsString) & Char(9) &
If(Required, "TRUE", "FALSE") & Char(9) &
If(CanBeDeleted, "TRUE", "FALSE") & Char(9) &
If(ReadOnlyField, "TRUE", "FALSE") & Char(10)
)

ここがメインの部分です。

3-1. Concat(_SPFields, ...)

  • _SPFields は、1レコード=1列情報を持つコレクション(テーブル)です。
  • Concat(コレクション, 式) は、
    コレクションの各レコードに対して を評価し、全部つなげたテキスト を返します。

つまり、

_SPFields に入っている各列について、「1行分のタブ区切りテキスト」を作り、それを上から順にずらーっと連結している

というイメージです。

3-2. 1 行分のフォーマット

Text(Title) & Char(9) &
Text(InternalName) & Char(9) &
Text(TypeDisplayName) & Char(9) &
Text(TypeAsString) & Char(9) &
If(Required, "TRUE", "FALSE") & Char(9) &
If(CanBeDeleted, "TRUE", "FALSE") & Char(9) &
If(ReadOnlyField, "TRUE", "FALSE") & Char(10)
  • Text(Title) などで、各フィールドを文字列に変換しています。
  • 各項目の間は Char(9)(タブ)で区切り → 列として分かれる
  • 行の最後に Char(10)(改行)を付ける → Excel上で「次の行」に進む

RequiredCanBeDeleted は true/false の論理値なので、

If(Required, "TRUE", "FALSE")

のようにして "TRUE" / "FALSE" の文字列に変換しています。

4. Copy() でクリップボードに送る

Copy(varClipboardText);
Notify("クリップボードにコピーしました。")

最後に、作成したテキストを Copy() 関数でクリップボードに送ります。

  • Copy(varClipboardText)
    varClipboardText の中身が、ユーザーのクリップボードにコピーされます。
  • Notify("クリップボードにコピーしました。")
    → コピーが完了したことをトースト通知でユーザーに知らせています。

あとはユーザーが Excel を開いて、任意のセルで Ctrl + V すれば、

1 行目にヘッダー
2 行目以降に _SPFields の中身

が表形式で貼り付けられます。

まとめ

今回は、Power Apps と Power Automate、そして SharePoint REST API を組み合わせて、リスト構造を可視化・出力するツールを作成しました。

SharePointリストを長く運用していると、「どの列が使われているのか分からない」「非表示になっている列の設定を忘れていた」 といったブラックボックス化が起きがちです。 今回紹介したアプリを使えば、ブラウザを行ったり来たりすることなく、一覧で設定状況を確認し、ワンクリックでExcel設計書として出力できます。

開発の初期段階だけでなく、運用中のメンテナンスや棚卸しにも非常に役立つツールですので、ぜひ自身の環境に合わせてカスタマイズして使ってみてください。

]]>
https://www.fulogabc.net/entry/sharepoint-list-visualize-export-powerapps-powerautomate/feed0
SOUNDPEATS Air5 Pro+ を1週間使った結論|買うべき人・やめた方がいい人https://www.fulogabc.net/entry/soundpeats-air5-pro-plus-reviewhttps://www.fulogabc.net/entry/soundpeats-air5-pro-plus-review#respondWed, 24 Dec 2025 09:00:00 +0000https://www.fulogabc.net/?p=3764

SOUNDPEATSさんより、「革新的なMEMSドライバーと最先端プラットフォームで、高解像度サウンドと高性能ANCを両立したワイヤレスイヤホン」をコンセプトに開発された Air5 Pro+ を提供いただきました。実際に ... ]]>

SOUNDPEATSさんより、「革新的なMEMSドライバーと最先端プラットフォームで、高解像度サウンドと高性能ANCを両立したワイヤレスイヤホン」をコンセプトに開発された Air5 Pro+ を提供いただきました。実際に使ってみたので、良かった点・微妙だった点も含めて紹介します。

クーポンコードもあるので、ぜひチェックしてね!

SOUNDPEATS Air5 Pro+ 完全ワイヤレスイヤホン
created by Rinker
Amazonクーポンコード情報
  • クーポンコード「SPA5P12PR03」
  • 使用期間:2026年1月25日(日)23時59分まで
  • ※本クーポンコードは、Amazonのセール価格やクーポンと併用可能です。

提供いただいたので、電車通勤や自宅での作業、アニメ・映画の視聴など、さまざまな場面で使ってみました。カナル型は苦手だと思い込んでいましたが、その印象が覆るほど気に入って使い込んでいます。

良かった点、微妙な点も紹介していくよ!

〖結論〗1.5万円以下で「音質」を最優先するなら、迷わず買い

結論から言うと、「予算1.5万円で、とにかく音が良い完全ワイヤレスイヤホンが欲しい」という方にとって、現時点で最強の選択肢です。

通常価格15,380円 ですが、クーポン等を活用して12,000円〜13,000円台で購入できるなら「即決レベル」と言えます。

逆に、2万円以上出す予算があり、ケースにディスプレイがついたJBLのようなギミックや、Apple製品との絶対的な親和性を求める場合は、他を検討する余地があります。しかし、純粋な「音の解像度」において、Air5 Pro+は価格の壁を超えた性能を持っています。

買いの判断基準

◯ 買い:Androidユーザー、少しでも良い音で音楽を聴きたい、予算1.5万円以内。

△ 待ち:「ながら聴き」がメインで耳を塞ぎたくない(Clip1などを推奨)。

× スルー:音質よりもブランドステータスや、極端な多機能を最優先する

スペック・使い勝手比較表

兄弟機である「Air5 Pro」や、形状の異なる「Clip1」、ハイエンド機の「JBL TOUR PRO 3」と比較しました。

Air5 Pro+Air5 Pro (兄弟機)Clip1JBL TOUR PRO 3
商品画像
参考価格15,380円 9,980円 9,980円約28,000円
ドライバーMEMS + 10mm DD 10mm DDのみ ダイナミックダイナミック他
装着感密閉型 (没入感◎)密閉型開放型 (楽)密閉型
音の傾向温かみ+超解像度 バランス重視ながら聴き向けオールラウンダー
ノイキャン-55dB (適応型) -55dB (適応型) 非対応最上位クラス
コーデックLDAC / aptX Lossless LDAC / aptX LosslessAAC/SBCLDAC対応
マルチポイント対応 対応対応対応
再生時間(単体)6時間 7.5時間 約2時間長め
再生時間(込み)30時間 37時間 約40時間長め
防水性能IPX5 IPX5IPX4等IPX5等
特徴コスパ最強の高音質安さ重視耳が疲れない全部入り・高機能

装着感・日常の快適さ(没入感は高いが長時間は休憩が必要)

装着感:しっかり密閉、音楽への没入感は抜群

カナル型(耳栓型)のため、耳の穴にしっかりとフィットします。本体重量は片耳約5gと軽量 で、着け心地自体は悪くありません。通勤電車の中など、周囲の音をシャットアウトしたいシーンでは非常に頼もしい存在です。

長時間使用:3時間が目安かも

在宅ワークで連続使用してみましたが、3時間を超えるとさすがに耳の中に「詰まっている感」が出てきます。これはAir5 Pro+に限らずカナル型の宿命です。 もし「1日中つけっぱなしでBGMを流したい」という用途であれば、比較対象の「Clip1」のようなオープンイヤー型の方が快適でしょう。

私は以前から「耳が蒸れるしカナル型は苦手」という立場でしたが、Air5 Pro+はこれまでのカナル型より不快感がかなり軽減されていました。集中したい場面、ノイズキャンセリングで没入して音楽を楽しみたい場面にはピッタリと感じました。

Air5 Pro+は「音楽をしっかり楽しむ」「移動中の騒音を消す」というメリハリのある使い方に向いています。

使い勝手(操作・アプリ・ケース・ストレス)

タッチ操作の感度は良好です。誤操作防止のためか、ワンタップでの反応エリアなどは適切に調整されている印象を受けました。コンパクトでポケットに収まりやすい形状です。取り出しやすさも合格点。

アプリ「PeatsAudio」

音にこだわりたい人や、いろいろ設定したい人は必須。ノイズキャンセリングのモード切替や、イコライザー調整ができます。プリセットも用意されているので、サクッと良い音を試してみたい人にもおすすめです。

Google Play で手に入れよう
AppStoreでダウンロード

接続安定性

最新チップ「QCC3091」搭載のおかげか、通勤ラッシュ時の駅構内でも接続が途切れることはありませんでした。
私自身は「混雑した場所で途切れる」経験がなかったので会社の同僚にも聞いてみたところ、イヤホンによっては途切れることがあるそうです。通勤で使いたい人にもAir5 Pro+はおすすめです。

音/通話(この価格でMEMS搭載は反則級)

これが1.5万円?と驚く「解像度」と「温かみ」 Air5 Pro+の最大の特徴は、「MEMSドライバー(中高域)」と「10mmダイナミックドライバー(低域)」のハイブリッド構成 です。

  • 高音域(MEMS担当):非常にクリアで、音の粒立ちが良いです。従来のバランスド・アーマチュア型のような金属的な硬さがなく、繊細で伸びやか です。シンバルの余韻やギターのカッティングが気持ちよく聞こえます。
  • 低音域(ダイナミック担当):スカスカになることはなく、しっかりと厚みがあります。「深みとキレのあるベース」 という表現通り、ボワつかずにドシッと支えてくれます。
  • ボーカル:ここが特に好印象でした。ハイテクなドライバーを積んでいるのに、人の声はデジタル臭さがなく、温かみがあって聴き疲れしません 。

片側3基のマイクとAIノイズキャンセリング により、カフェでのWeb会議でもこちらの声をクリアに届けることができました。ビジネス用途でも十分に通用します。

便利機能まとめ

地味ですが、以下の機能があるおかげで「日常のストレス」が大きく減ります。

マルチポイント接続

PCでWeb会議をしつつ、個人のスマホに着信があってもそのまま出られます。これは現代の必須機能です。切り替えもスムーズでした 。

強力なANC(-55dB)

「アダプティブ(適応型)」なので、環境に合わせて強さを自動調整してくれます。電車内では「ゴーッ」という走行音がスッと消え、音楽に集中できます。

良かったところ

価格破壊レベルの音質

本来2〜3万円クラスの技術を、1.5万円で全て搭載している点が驚異的です

最大の特徴は、高音域を担う最新鋭「xMEMSドライバー」。従来の4倍の応答速度を持ち、金属的な硬さのない「繊細で温かい高音」を実現します。 さらに、それを駆動する専用アンプを独立搭載し、LDAC・aptX Losslessでハイレゾ音源も余すことなく伝送

「高い解像度」と「聴き疲れしない温かみ」を両立したこのサウンドは、同価格帯の常識を明らかに超えています。

全部入りのコーデック対応

iPhone向けのAACはもちろん、Androidでのハイレゾ再生に必須のLDAC、さらにCD音質を劣化なく伝送するaptX Losslessまで対応している点は驚異的です。

通常この価格帯では省略されがちなLossless対応により、Snapdragon Sound認定スマホであれば、ワイヤレスの常識を覆す“無圧縮”の濃密なサウンドを楽しめます 。 さらに次世代規格LE Audio (LC3) もサポート 。最新のスマホに機種変更しても、最高音質と接続性能を引き出せる、まさに「死角なし」の仕様です 。

ANC性能の高さ

ノイズキャンセリングは、ブランド史上最強となる最大-55dBの性能を誇ります 。 街に出かけ、いろいろな場所へ移動しながら試しましたが、どこでも周囲の音をしっかり消してくれました。

単に消音力が強いだけでなく、「AI適応型(アダプティブ)」技術の搭載が大きなメリットです 。AIが周囲の騒音レベルや耳への装着状態をリアルタイムで検知し、その場に最適な強度へ自動で調整してくれます 。

電車内のような轟音下では強力にノイズをカットし、カフェのような場所では圧迫感を抑えた自然な静寂を提供します 。手動でモードを切り替える手間なく、常に「音楽に没頭できる環境」を賢く作ってくれるため、移動中や作業時の集中力が格段に上がります 。専用アプリを使えば、状況に応じたモード選択も可能 。

デザインと質感

マットなブラックの本体にゴールドのアクセントがあり、安っぽさがありません。

イヤホンの音が出る部分もゴールドで、細部までこだわられたデザインになっています。

微妙だったところ

長時間の連続使用には不向き

カナル型特有の圧迫感は避けられません。4時間以上の連続使用や、「つけていることを忘れたい」という用途なら、オープンイヤー型のClip1やAir5(無印)の方が良いかもしれません。

ケースのバッテリー持ち

本体単体で6時間、ケース込みで30時間で十分ですが、兄弟機のAir5 Pro(37時間)やClip1(40時間)と比較するとやや短めです。高出力なアンプやMEMSを動かしている代償かもしれません。

ワイヤレス充電は非対応

私は特に困らないのですが、ワイヤレス充電には対応していません。ワイヤレス充電をしたいという方には少し不便に感じるかもしれません。

おすすめな人 / やめとけ

おすすめな人

  • Androidユーザー:LDACやaptX Adaptive/Losslessの恩恵をフルに受けられます 。
  • 音質にこだわりたいが予算は抑えたい人:2〜3万円クラスの音質を1.5万円で手に入れられます。
  • 通勤・通学での騒音を消したい人:強力なANCが必要です。

やめとけ(他を検討すべき人)

  • 耳の穴を塞ぐのが苦手な人:カナル型が体質に合わない場合は、オープンイヤー型を選びましょう。
  • iPhoneユーザーで、AAC接続のみで十分な人:Air5 Pro+の性能は発揮できますが、aptX Losslessなどの機能はオーバースペックになる可能性があります。
  • バッテリー持ち最優先の人:週に1回も充電したくない、というレベルなら、よりスタミナのあるモデルがあります。

同梱物・付属品

同梱されているものはこちら。説明書は日本語でも記載されているので、困ることはありませんでした。

  • イヤホン本体
  • 充電ケース
  • USB Type-C充電ケーブル
  • イヤーチップ(S/M/L)※Mは本体装着済み
  • 説明書、アプリ説明書
  • ステッカー

充電ケーブルやユーザーガイドがきちんと同梱されており、別途調べたり充電コードを用意する必要がありません。個人的に、この点はかなり嬉しかったです。

説明書が日本語表記にも対応しており、利用時に困ることはありませんでした。

SOUNDPEATS Air5 Pro+スペック詳細

商品画像
タイプワイヤレス
形式カナル型
本体操作タッチ
ドライバー方式MEMSドライバー「Cowell」
10mmダイナミックドライバー(デュアル銅線、PU +PEEK)
ハイレゾ認証認証済み
パワーアンプチップ搭載(XAA-2000 Aptos)
Snapdragon Sound対応
LE Audio対応
再生周波数帯域20Hz~40KHz
対応コーデックSBC/AAC/LC3/LDAC/aptX/aptX Adaptive/aptX Lossless
BluetoothチップQCC3091
Bluetoothバージョン5.4
BluetoothプロファイルHSP / HFP / A2DP / AVRCP
最大持続時間(単体6時間
最大持続時間(本体)30時間
重量 (単体)5g
重量 (本体)51.11g
サイズ (単体)34.60×19.87×23.50mm
サイズ (本体)66.88×48.33×26.92mm
充電時間 (単体)1時間
充電時間 (本体)2時間
充電コネクタUSB Type-C
急速充電対応(10分で2時間利用可能)
内蔵マイク片側3基
Adaptive ANC対応(最大 -55dB)
通話用ノイズキャンセリングSOUND+
風切り音低減対応
マルチポイント対応
ゲームモード対応(60ms 低遅延)
防水性能IPX5

SOUNDPEATS Air5 Pro+ 完全ワイヤレスイヤホン
created by Rinker
Amazonクーポンコード情報
  • クーポンコード「SPA5P12PR03」
  • 使用期間:2026年1月25日(日)23時59分まで
  • ※本クーポンコードは、Amazonのセール価格やクーポンと併用可能です。

]]>
https://www.fulogabc.net/entry/soundpeats-air5-pro-plus-review/feed0
GCPでOAuth 2.0リフレッシュ & アクセストークンを取得する方法https://www.fulogabc.net/entry/gcp-oauth2-refresh-access-tokenhttps://www.fulogabc.net/entry/gcp-oauth2-refresh-access-token#respondMon, 24 Nov 2025 08:49:31 +0000https://www.fulogabc.net/?p=3634

Google Cloud Platform (GCP) でAPIを活用する際、OAuth 2.0 認証を利用する機会が多くあります。本記事では、GCP上でリフレッシュトークンとアクセストークンを取得して、API呼び出しに ... ]]>

Google Cloud Platform (GCP) でAPIを活用する際、OAuth 2.0 認証を利用する機会が多くあります。本記事では、GCP上でリフレッシュトークンとアクセストークンを取得して、API呼び出しに利用するまでの手順を解説します。

OAuth同意画面を設定

GCPコンソールで 「API とサービス」 > 「OAuth 同意画面」 を開きます。

Google Auth Platformの構成画面になります。Google Cloudのプロジェクト単位で作成する形になります。

「開始」ボタンより情報を登録していきます。

内部か外部かはプロジェクトの利用範囲等に応じて設定してください。

連絡先情報としてメールアドレスを登録します。

OAuth クライアント IDを作成

OAuth クライアント IDを作成します。

アプリケーション種類は「Web アプリケーション」

承認済みリダイレクトURI に次を追加します。(OAuth 2.0 Playground を使うため)

コピーしました!

URI
https://developers.google.com/oauthplayground

クライアント作成直後、シークレットキーを確認できます。

2025年11月以降は、クライアントシークレットはこの画面でのみ確認やダウンロードが可能となる見込みです。必ずダウンロードやメモを取り保管しましょう。

リフレッシュトークンを取得

ブラウザで OAuth 2.0 Playground を開きます。
https://developers.google.com/oauthplayground

右上の ⚙ 設定“Use your own OAuth credentials” をオンにして、先ほど作った Client ID / Client Secret を入力 → Close。

左のスコープで 利用したいの権限を選選びます。

私は「https://www.googleapis.com/auth/calendar.events(イベントの作成・更新)」を選択しました。

“Authorize APIs” ボタンをクリックし、Googleアカウントで認証を行います。

アカウント選択後、「このアプリはGoogleで確認されていません」と表示されますが、左下の詳細から進み、URLへアクセスします。

URLを開くとOAuth 2.0 Playgroundに戻ってきます。

右下にリフレッシュトークン等が表示されています。

{
  "access_token": "{アクセストークン}",
  "scope": "https://www.googleapis.com/auth/calendar.events",
  "token_type": "Bearer",
  "expires_in": 3599,
  "refresh_token": "{リフレッシュトークン}"
}

あとはリフレッシュトークンを使い、アクセストークンの生成で活用できます。

トークンの利用方法・注意点

  • アクセストークンは有効期限 (expires_in) が切れると使えなくなるため、リフレッシュトークンを使って新しいアクセストークンを取得する必要があります。
  • リフレッシュトークンは一度取得すれば長期的に使用できることが多いですが、トークンの管理・保護は慎重に行ってください。
  • OAuth 2.0 Playgroundは開発/テスト用途に便利ですが、本番環境では自前でトークン取得・更新ロジックを組み込むAPIクライアント実装を検討してください。
  • GCPの設定画面やポリシーは随時変更されることがあるため、Google公式ドキュメントも併せて参照することを推奨します。

]]>
https://www.fulogabc.net/entry/gcp-oauth2-refresh-access-token/feed0
【SOUNDPEATS】イヤーカフの完成形! Clip1 は最高だったhttps://www.fulogabc.net/entry/soundpeats-clip1-reviewhttps://www.fulogabc.net/entry/soundpeats-clip1-review#respondThu, 20 Nov 2025 11:38:37 +0000https://www.fulogabc.net/?p=3636

SOUNDPEATSさんからイヤホンの提供を 今回はイヤーカフ型という、耳に挟んで使うタイプのイヤホンをSOUNDPEATSさんから提供いただきました。実際に使ってみたので、紹介していきます! Clip1は、耳をふさがな ... ]]>

SOUNDPEATSさんからイヤホンの提供を

今回はイヤーカフ型という、耳に挟んで使うタイプのイヤホンをSOUNDPEATSさんから提供いただきました。実際に使ってみたので、紹介していきます!

Clip1は、耳をふさがないイヤーカフ型のデザインが特徴で、一般的なカナル型や骨伝導とは違った「第3の選択肢」として注目されています。
片耳約5gという軽さに加えて、形状記憶合金「N-Flex Arch™」を採用しているので、耳の形に合わせて柔らかくフィットし、長時間でも快適。
メガネやマスクをしていても干渉しにくいのがかなり便利です。

クーポンコードもあるので、ぜひチェックしてね!

クーポンコード情報
  • クーポンコード「SPZYCLPHR11」
  • 使用期間:2025年12月21日(日)23時59分まで

良かった点、微妙な点も紹介していくよ!

【結論】長時間でも快適なイヤホン

耳に挟むタイプや骨伝導タイプのイヤホンは、長時間着用すると痛みや違和感を感じることがあります。しかし、この SOUNDPEATS Clip1 はそうした不快感がなく、長時間つけていても快適でした。

以前、CCイヤーカフ型のイヤホンも使わせていただいていましたが、今回は着用感の違和感がほぼなくなっていると感じました。

SOUNDPEATS Clip1 SOUNDPEATS
CCイヤーカフイヤホン
SOUNDPEATS Air5SOUNDPEATS
RunFree
価格9,980円7,280円9,980円6,680円
Bluetooth接続の安定感超安定超安定安定安定
防水IPX5IPX5IPX5IPX4
音質良い良い普通普通
ノイズキャンセリングなしなし十分なし
操作性タッチタッチタッチ物理ボタン
再生時間約40時間約24時間約30時間約14時間
充電時間約2時間1.8時間約2時間約1.6時間
イヤーカフ型イヤーカフ型インナーイヤー型ネックバンド型

イヤーカフ型が苦手な人にもおすすめできるつけ心地

カナル型やインナーイヤー型とは異なり、耳に引っ掛けるようにして装着します。こうした形状のイヤホンで最も気になるのは装着感で、耳が痛くなったり、メガネやマスクと干渉して使いづらくないか、という点です。

イヤーカフ型は少し違和感があり、あまり好ましく感じていなかったのですが、Clip1 はかなり装着感が改善されていました。合計で約20時間ほど着用しましたが、「装着していることを意識しない」ほど快適でした。

一番驚いたのは、オープン型なのにしっかりと低音が鳴ること。
Clip1 には φ12mmのデュアルマグネットダイナミックドライバーが搭載されており、SOUNDPEATS 独自の DynamicEQ™ Pro アルゴリズム により、AAC接続でも音の立体感が感じられます。
実際にiPhoneでApple Musicのロスレス音源を聴いてみましたが、耳を塞いでいないのに迫力を感じるサウンドで、ジャンル問わず楽しめました。

Dolby&LDAC対応でより良い音を聴ける

ヘッドホンに比べると音質はやや劣るものの、それでも少し前の世代と比べると大幅に音が改善されています。Clip1 は “LDAC” という SONY が開発した高音質 Bluetooth コーデックに対応しており、通常の “SBC” コーデック形式に比べて約3倍の情報量を伝送できるため、音の細部まで忠実に再現され、クリアで奥行きのある臨場感あるサウンドが楽しめます

映画館でもよく採用されている “Dolby Audio モード” にも対応しています。これにより「もうヘッドホンは必要ないのでは?」と思うほどの体験になりました。私自身もヘッドホンの購入を検討していましたが、「これで十分ではないか」と感じました。

ケースに左右を気にせず入れてOK

ケースに収納するとき、左右を間違えてうまくハマらずイライラした経験はありませんか?このイヤホンは、左右を気にせずケースに入れても問題ありません!

左右のチャンネルも自動で再認識されるため、特に気にする必要はありません。些細なことではありますが、こういった点がストレスにならず快適です。

便利機能が盛りだくさん

Clip1 は機能面でもユーザー目線の工夫が光ります。

  • 左右自動識別(AutoSense™…装着方向に応じて左右チャンネルを切替えてくれるので、つける向きを意識する必要なし
  • 装着検出…外すと自動停止→つけると再生再開
  • 急速充電…10分の充電で約2時間再生と使い勝手が良い
  • マルチポイント対応…スマホとPCにつなぎ替え不要で、在宅ワークも快適
  • 落下検知(今後ファームウェア更新で対応)
    こうした機能は「あると助かる」けど意外と搭載されていないことが多いので、個人的にはかなりポイントが高かったです。

Clip1がおすすめな人

  • メガネやマスクをつけて過ごす方
  • 耳への負担をかけたくない方
  • 聴きながら周囲の音も聞きたい方
  • オープン型でも音質に妥協したくない方
  • 通勤・家事・動画視聴に使いたい方

SOUNDPEATS CCイヤーカフイヤホンの同梱物

同梱されているものはこちら。説明書は日本語でも記載されているので、困ることはありませんでした。

  • 本体
  • 充電ケーブル(TypeA to TypeC)
  • ユーザーガイド
  • Peats Audioガイド
  • シール

充電ケーブルやユーザーガイドがきちんと同梱されており、別途調べたり充電コードを用意する必要がありません。個人的に、この点はかなり嬉しかったです。

説明書が日本語表記にも対応しており、利用時に困ることはありませんでした。

SOUNDPEATS CCイヤーカフイヤホンの詳細なスペック

SOUNDPEATS Clip1
価格9,980円
Bluetooth接続の安定感超安定
防水IPX5
音質良い
ノイズキャンセリングなし
操作性タッチ
再生時間約40時間
充電時間約2時間
イヤーカフ型

クーポンコード情報
  • クーポンコード「SPZYCLPHR11」
  • 使用期間:2025年12月21日(日)23時59分まで

]]>
https://www.fulogabc.net/entry/soundpeats-clip1-review/feed0
【Power Appsツール】Googleマテリアルアイコンを画像コードに変換するツールhttps://www.fulogabc.net/entry/powerapps-google-material-icon-code-toolhttps://www.fulogabc.net/entry/powerapps-google-material-icon-code-tool#respondMon, 15 Sep 2025 01:50:53 +0000https://www.fulogabc.net/?p=3605

作成したばかりのツールでバグ等あるかもしれません。バグ等はコメントにてご連絡ください。 transform Material Icons to Power Apps GoogleマテリアルシンボルをPower Apps用 ... ]]>

作成したばかりのツールでバグ等あるかもしれません。バグ等はコメントにてご連絡ください。

transform Material Icons to Power Apps

GoogleマテリアルシンボルをPower Apps用のSVG形式に変換します。

search

英語名の一部を入力すると候補が表示されます。

アイコンがここに表示されます

EncodeUrl 関数を使用した形式です。色コード部分を変数などに置き換えることで動的に変更できます。

info 使い方

  • 利用方法: 上のボックス(数式)をコピーし、Power Appsの画像コントロールのImageプロパティに貼り付けます。
  • 色を変える: 数式内の '${colorText.value}' の部分を Self.ColorUserColor などの変数に置き換えることで、Power Apps上で動的に色を変更できます。
]]>
https://www.fulogabc.net/entry/powerapps-google-material-icon-code-tool/feed0
【Power Apps+Automate】Teamsで「いいね」してない人に対してメンションするアプリhttps://www.fulogabc.net/entry/power-apps-automate-teams-mention-people-who-did-not-likehttps://www.fulogabc.net/entry/power-apps-automate-teams-mention-people-who-did-not-like#respondFri, 12 Sep 2025 10:00:00 +0000https://www.fulogabc.net/?p=3542

Teamsで「いいね」をしてない人に対してスケジュール実行でメンションをするというフローをわたるふさんという方が2022年に作成しており、私も使わせていただいていました。 しかし、 といったことができませんでした。 上の ... ]]>

Teamsで「いいね」をしてない人に対してスケジュール実行でメンションをするというフローをわたるふさんという方が2022年に作成しており、私も使わせていただいていました。

しかし、

  • チームメンバー全員ではなく、特定の人物だけにメンションしたい
  • 予約した投稿を簡単に取り消したい

といったことができませんでした。

上の機能をPower Appsと組み合わせることで実装しましたので紹介します。

アプリ・フローのダウンロード

アプリとフローはGitHubに公開しています。下記URLからダウンロードしてご利用いただけます。

機能など

実際のアプリ画面はこちらです。

アプリでリマインド先を設定し実行することで、チャネルにメンションしたり、いいねしてない指定した人にメンションしたり、予約投稿したりできます。

根本的にはわたるふさんのフローで、アプリでは下記2つの機能を追加しています。

  • チームメンバー全員ではなく、特定の人物だけにメンションしたい
  • 予約した投稿を簡単に取り消したい

解説

各パーツの機能や設定値などを紹介していきます。

データ

データとして下記3つを追加します。

  • Microsoft Teams
  • Office365グループ
  • PowerAutomate管理

「予約投稿取り消し機能」OnStart

予約投稿を取り消す方法として、下記方法で実装しています。

  1. 予約投稿時、自分宛てにアプリ起動URLにパラメータを付与したURLを通知する
  2. 通知されたURLからアプリを起動すると、Power Apps上でフローの取り消しを実行する。

アプリのAPP>OnStartに下記を設定します。

コピーしました!

OnStart
//URLから起動
If(IsBlank(Param("Category")) = false, //URLパラメータに何か入っていれば //パラメーターをグローバル変数に格納	Set(varParamCategory,Text(Param("Category"))); Set(varParamId,Text(Param("Id"))); //フローキャンセル処理 PowerAutomate管理.CancelFlowRun( "Default-99b882ac-a043-4d2e-9579-dbbef4dff629", "006e853e-817a-4a13-2a04-6045298f4c69", varParamId ); Notify("予約投稿を取り消しました",NotificationType.Information)
);

URL構成は下記のように”Category”と”Id”を付け加えています。

URL
https://apps.powerapps.com/play/e/【環境ID等・略】&Category=ReminderCancel&Id=【フロー実行ID】

このURLをPower Automateで作成し、Teamsへ通知。取り消す際は通知されたURLへアクセスすることで、フローが取り消されるという動作になっています。

チーム

まずは、Teamsのチームを選択できるようにします。ドロップダウンのパーツのそれぞれのプロパティに下記を設定します。

コピーしました!

Items
Sort(MicrosoftTeams.GetAllTeams().value,displayName,SortOrder.Ascending)

次に、下記2つもここで実装します。

  • チャネル情報も取得し、グローバル変数に格納する
  • チームメンバーをPower Automate経由で取得する

もう少し別のパーツで機能として付けてもいいと思いますが、チームが確定したタイミングで上記2つが確定するため、このタイミングでデータの取得・準備を済ませます。

同じくチームのドロップダウンのパーツのOnChangeに下記を設定します。

コピーしました!

OnChange
//loading画面
UpdateContext({_loadingMenu:true});
//チームIDを格納
Set(ChannelData,Blank());
Set(ChannelData,MicrosoftTeams.GetChannelsForGroup(drp_team.Selected.id).value);
//Chatデータをリセット
Set(chatData,Blank());
//チームメンバーをリセット
UpdateContext({_colMemberList: Blank()});
//エラー検知:チームIDの空白を検知
If( IsBlank( drp_team.Selected.id), UpdateContext( { _teamIdError: "true" } ), UpdateContext( { _teamIdError: "false" } ) );
// 条件判定と処理
If( Or( _teamIdError="true" ) ,// エラーメッセージ Notify("エラーです。確認をお願いします。" & If(_teamIdError="true","「チームが選択されていません」 ","") , NotificationType.Warning); , //Power Automate実行 UpdateContext({_colMemberListtmp: メンバーリスト取得.Run(drp_team.Selected.id)}); //実行結果をテーブルへ変換 UpdateContext( { _colMemberList: ForAll( Table(ParseJSON(_colMemberListtmp.memberlist)), { id: Text(ThisRecord.Value.id), displayName: Text(ThisRecord.Value.displayName), jobTitle: Text(ThisRecord.Value.jobTitle), mail: Text(ThisRecord.Value.mail), preferredLanguage: Text(ThisRecord.Value.preferredLanguage) } ) } );
);
//loading画面 UpdateContext({_loadingMenu:false});

Power Appsではチームメンバーを100人以上取得できないため、Power Automate経由で取得します。

また、取得するデータや後続の操作等で分かりやすさやエラー防止の為、すでに取得したデータについてはクリアしてからデータを取得し直しています。

ローディング画面も準備していますが、データ取得中の誤操作を防ぐためです。

Power Automateは下記の様になっています。

特に特別なことはせず、Power AppsからTeamIDを受け取り、「グループメンバーの一覧表示」でメンバーを取得しアプリへ文字列にして返してています。(有料プランの場合はHTTPアクション等で返却しても良いと思います)

「グループメンバーの一覧表示」の設定の改ページを設定することで、より多くの人数分のデータが取得できます。

チャネル

選択したチームに応じて、チャネルを表示し選択できるようにします。チーム選択時、「ChannelData」というグローバル変数に格納しているので、Itemsにそのまま入れます。(Sortで並べ替えしています)

コピーしました!

Items
Sort(ChannelData,displayName,SortOrder.Ascending)

チャネルを選択することで、リマインド投稿したい投稿先が確定します。このタイミングでチャットデータを取得します。

コピーしました!

OnChange
//チャットデータを変数に格納
Set(chatData,Blank());
Set(chatData,MicrosoftTeams.GetMessagesFromChannel(drp_team.Selected.id,drp_channel.Selected.id).value);

リマインド先

リマインドをしたい投稿を選択できるようにします。閉じたり開いたりできるようにしていますが、ギャラリーに直接表示するだけで十分だと思います。閉じたり開いたりする設定などは、GitHubからダウンロードしたアプリをインポートしてご確認ください。ココでは最低限紹介します。

ギャラリーに下記を設定します。

コピーしました!

Items
chatData

メンションの宛先

「チャネルにメンションする」か「いいねしてない人にメンションする」かを選択できるようにします。

ドロップダウンのItemsに下記を設定します。

コピーしました!

Items
Table( { id: 1,choices: "チャネルにメンションする" }, { id: 2,choices: "いいねしてない人にメンションする" }
)

メンションの宛先

「いいねしてない人にメンションする」の場合にのみ表示させ、チームメンバーを選択できるようにします。チームメンバーはチーム選択時にAutomate経由で取得したデータを利用します。

わたるふさんのフローでは決まってチームメンバー全員が対象でしたが、ここでチームメンバー内の特定の数人を選択して実行することが可能になります。

コンテナで囲っているので、コンテナのVisibleに、「いいねしてない人にメンションする」(idが2)のときに表示できるように設定します。

コピーしました!

Visible
If(drp_メンション宛先.Selected.id=2,true,false)

メンバー選択のコンボボックスには下記を設定します。

コピーしました!

Items
_colMemberList

複数人に対してのメンションも動作するようになっていますので、「複数人の選択を許可」をONにします。

いつ実施するか

「いますぐ」か「日時を指定する」かを選択できるようにします。

ドロップダウンのItemsに下記を設定します。

コピーしました!

Items
Table( { id: 1,choices: "いますぐ" }, { id: 2,choices: "日時を指定する" }
)

予約日時

予約投稿の場合のみ表示し、予約する日時を設定できるように、日付の選択やドロップダウンを配置しています。

コンテナで囲っているので、コンテナのVisibleに、「日時を指定する」(idが2)のときに表示できるように設定します。

コピーしました!

Visible
If(drp_いつ.Selected.id=2,true,false)

予約日時

予約投稿の場合にのみ表示し、選択肢として「チャネルに投稿する」、「自分だけに知らせる」を選択できるようにします。

予約投稿の場合にのみ表示させる方法は先程と同じですので、割愛します。

選択肢として、ドロップダウンに下記を設定します。

コピーしました!

Items
Table( { id: 1,choices: "チャネルに投稿する" }, { id: 2,choices: "自分だけに知らせる" }
)

本文

リマインド時にテキストを付けられるように、リッチテキストエディターを作成します。

ボタン

一番下に配置している実行ボタンです。

処理をいくつかに分けて説明します。

エラーフラグ設定

チームの未選択や、メンション先の未選択の場合、フローが動作する条件を満たさない為、未選択かどうかを判定し、コンテキスト変数に格納しています。

コピーしました!

OnSelect
// --- 基本エラーフラグ(boolean)を一括設定 -------------------------------
UpdateContext({ _teamIdErrorB: IsBlank(drp_team.Selected.id), //エラー検知:チームIDの空白を検知 _channelIdErrorB: IsBlank(drp_channel.Selected.id), //エラー検知:チャネルIDの空白を検知 _channelReplyIdErrorB: IsBlank(gal_リマインド先.Selected.id), //エラー検知:リマインド先、返信用IDの空白を検知 _mentionAtesakiErrorB: IsBlank(drp_メンション宛先.Selected.id), //エラー検知:メンションの宛先の空白を検知 _implementationTimingErrorB: IsBlank(drp_いつ.Selected.id) //エラー検知:いつ実施かの空白を検知
});

予約投稿のチェック等

予約投稿の場合のエラーチェックや日時をAutomateに渡す形に加工しています。

エラーのチェックは下記2つのチェックです。

  • 設定した日時が過去ではないか
  • 設定した日時は30日以内か(Automateの実行最大時間)

コピーしました!

OnSelect
// 予約投稿のタイミングの選択状態を保持(boolean)
Set(_isReserveB, drp_いつ.Selected.id = 2);
// --- 予約投稿のときだけ日時を合成 & 差分(分)を計算 ----------------------
If( _isReserveB, // SelectedDateTime = 選択した日付 + 時 + 分 Set( SelectedDateTime, DateAdd( DateAdd( DateValue(dte_予約日時_日.SelectedDate), Value(drp_予約日時_時.Selected.Value), TimeUnit.Hours ), Value(drp_予約日時_分.Selected.Value), TimeUnit.Minutes ) ); Set(DaysDifference, DateDiff(Now(), SelectedDateTime, TimeUnit.Minutes)); UpdateContext({ _yoyakuJouhouErrorB: IsBlank(drp_予約情報.Selected.id), //エラー検知:予約情報の通知先空白 _dateTimeErrorB: DaysDifference >= 43200, // 30日 = 43200分 _dateTimeMiniErrorB: DaysDifference <= 0 // 過去 }), // 日時指定でない場合は日時系エラーなし UpdateContext({ _yoyakuJouhouErrorB: false,_dateTimeErrorB: false, _dateTimeMiniErrorB: false })
);

メンションの宛先メンバー作成等

メンションの宛先が「いいねしてない人」の場合、対象者のメールアドレスを配列でまとめておきます。また、チャネル宛の場合は空白を渡してエラーになるので、適当に「1」を渡すように設定します。

コピーしました!

OnSelect
// --- メンションの宛先作成:メンションの宛先------------------ If( drp_メンション宛先.Selected.id=2 , //いいねしてない人にメンションの場合:宛先のメールアドレスだけを配列で渡す為に変換 Set(_channelMentionMember, JSON(ShowColumns(cmb_メンションメンバー.SelectedItems,mail),JSONFormat.Compact)); , //チャネルにメンションの場合:フローで不要なので適当に「1」を送る Set(_channelMentionMember, "1"); );

メンションの宛先メンバー作成等

エラーの変数とメッセージのコレクションを作り、エラーの判定を行い、エラーがゼロの場合、Power Automateを実行する形にしています。

コピーしました!

OnSelect
// --- エラーコレクションを作って、まとめて通知 or 成功処理 ------------------
ClearCollect( _errorsB, { flag: _teamIdErrorB, msg: "「チームが選択されていません」" }, { flag: _channelIdErrorB, msg: "「チャネルが選択されていません」" }, { flag: _channelReplyIdErrorB, msg: "「リマインド先が選択されていません」" }, { flag: _mentionAtesakiErrorB, msg: "「メンションの宛先が選択されていません」" }, { flag: _implementationTimingErrorB,msg: "「『いつ実施しますか?』が選択されていません」" }, { flag: _dateTimeErrorB, msg: "「予約投稿は720時間(30日)未満で設定してください」" }, { flag: _dateTimeMiniErrorB, msg: "「予約投稿が過去の日時になっています。」" }, { flag: _yoyakuJouhouErrorB, msg: "「予約投稿の通知先が選択されていません。」" }
);
If( CountRows(Filter(_errorsB, flag)) > 0, // ---- エラーあり:まとめて警告 ---- Notify( "エラーです。確認をお願いします。 " & Concat(Filter(_errorsB, flag), msg & " "), NotificationType.Warning ), // ---- エラーなし:Power Automate 実行 → JSON をテーブル化 ---- Powerapps_リマインド.Run( drp_team.Selected.id, //チームID drp_channel.Selected.id, //チャネルID gal_リマインド先.Selected.id, //リマインド先チャットID drp_メンション宛先.Selected.id, //メンションの宛先 _channelMentionMember, //メンションの宛先メンバー drp_いつ.Selected.id, //いつ実行か Text(SelectedDateTime,DateTimeFormat.UTC), //予約投稿日時 drp_予約情報.Selected.id, //予約情報どこに投稿か User().Email, //実行者メール drp_channel.Selected.displayName, //チャネル名 rtx_本文.HtmlText //本文 );
);

参考記事など

]]>
https://www.fulogabc.net/entry/power-apps-automate-teams-mention-people-who-did-not-like/feed0
【Power Automateツール】Jsonのパスを出力するツールhttps://www.fulogabc.net/entry/power-automate-json-path-toolhttps://www.fulogabc.net/entry/power-automate-json-path-tool#respondFri, 12 Sep 2025 09:06:56 +0000https://www.fulogabc.net/?p=3597

作成したばかりのツールでバグ等あるかもしれません。バグ等はコメントにてご連絡ください。]]>

作成したばかりのツールでバグ等あるかもしれません。バグ等はコメントにてご連絡ください。

JSONPath & Power Automate 式ジェネレーター

JSONを貼り付け → 検証/整形 → 下のツリーから項目を選択 → JSONPathとPower Automate式をコピーできます。データはサーバーに送信されません。

1. 入力

2. 検索・フィルタ

3. JSONツリー

4. 生成結果(単一)

JSONPath
Power Automate式
アクション名(既定): 例: body(‘Parse_JSON’)

5. 一括生成キュー

キーJSONPathPA式操作
このツールはクライアントサイドで動作し、データは保存・送信されません。 v1.0.1

]]>
https://www.fulogabc.net/entry/power-automate-json-path-tool/feed0
【Power Automate】Formsの問い合わせを複数の添付ファイルのリンク付きで通知する方法https://www.fulogabc.net/entry/forms-inquiries-with-multiple-attachment-linkshttps://www.fulogabc.net/entry/forms-inquiries-with-multiple-attachment-links#respondSat, 16 Aug 2025 07:43:34 +0000https://www.fulogabc.net/?p=3485

Formsで問い合わせを受け、それをTeamsに通知するフローを作成しました。 単純にTeamsに通知するだけであれば簡単にできますが、通知する際に添付ファイルのURLも通知できるようしました。 フローはGitHubに公 ... ]]>

Formsで問い合わせを受け、それをTeamsに通知するフローを作成しました。

単純にTeamsに通知するだけであれば簡単にできますが、通知する際に添付ファイルのURLも通知できるようしました。

フローのダウンロード

フローはGitHubに公開しています。下記URLからダウンロードしてご利用いただけます。

全体像

全体像は簡単にこんな感じです。Formsに登録された内容をもとに、チャネルと登録者へ通知を行います。チャネルへの通知はFormsに通知先の質問を設け、その選択に応じて通知先を変更します。

また、通知する際には内容に加え添付ファイルの共有URLも一緒に通知を行います。

下記のFormsに登録をすると、

Teamsのチャネルと登録者本人に通知がされます。

添付ファイルは選択すると開くことができます。

Forms

Formsは下記のように作成しています。

Formsは個人で作る場合と、グループで作成する2通りの作り方があります。今回どちらにも対応できるよう、それぞれの作り方を紹介します。また、長期間利用するFormsの場合やチームで運用するFormsの場合はグループフォームで作成されることをおすすめします。作り方やグループフォームについては、下記の記事が分かりやすいので確認してください。

フロー解説

分割して解説していきます。

新しい応答が送信されるとき

トリガーとして「新しい応答が送信されるとき」を設定し、フォームIDに作成したFormsを設定します。

フォームIDはドロップダウンから選択もできますが、グループフォームの場合は選択肢に表示されません。グループフォームの場合は、下記方法でフォームIDを確認して設定してください。

応答の詳細を取得する

「新しい応答が送信されるとき」では詳細な情報が取得できない為、「応答の詳細を取得する」を設定して登録された情報を取得します。

フォームIDは先程と同じように設定し、応答IDには「新しい応答が送信されるとき」で取得した「応答ID」を設定します。

コピーしました!

応答ID
@{triggerOutputs()?['body/resourceData/responseId']}

変数を初期化する

今回は通知先のチャネルを、Formsに登録された内容をもとに変更します。IDを任意に変更させられるよう、変数として扱います。同じように添付ファイルの情報についても、Formsに毎回添付されるとは限らない為、変数として扱い後続の処理をシンプルにします。

変数は全て文字列で値は空白で作成しておきます。

ユーザーの検索 (V2)

Formsに登録した人の名前を取得する為「ユーザーの検索 (V2)」を使用します。検索語句にはメールアドレスを設定しますが、アドレスは「応答の詳細を取得する」から取得できます。

コピーしました!

検索語句
@{outputs('応答の詳細を取得する')?['body/responder']}

Formsで「名前を記録する」をONにしておく必要があります。

スイッチ

Teamsへ通知を行いますが、Formsで選択された通知先に応じて通知先を設定します。Teamsのチャネルに投稿するにはチームIDとチャネルIDが必要ですが、ここでそれぞれ変数に設定していきます。

下記に例でを設定値を記載していますが、「raa3799e7254647d0a3cf983036f496b0」はフォームによって異なる為、実際には動的コンテンツから「応答ID」を選択してください。

コピーしました!

オン
@{outputs('応答の詳細を取得する')?['body/raa3799e7254647d0a3cf983036f496b0']}

変数の設定では条件に応じて、通知を行うチームIDとチャネルIDをそれぞれ手入力します。チームIDとチャネルIDは下記記事に記載のPower Appsのアプリをダウンロードしてインポートすることで確認ができます。

Power Appsを使わずに確認する場合は下記記事の方法で確認ができます。

条件

添付ファイルがある場合は添付ファイルのURLもTeamsで通知を行うため、添付ファイルのURLを作成します。添付ファイルが無い(True)の場合は何もせず、1つ以上添付されている場合にURLを作成しています。

条件には下記の様に設定することで、添付ファイルの有無を判定しています。empty関数で空白かどうかを確認しています。空白の場合「True」となり、なにか値がある場合は「False」となります。

コピーしました!

条件の左側
@{empty(outputs('応答の詳細を取得する')?['body/r3604874417984f6e93da3af27466b768'])}

「r3604874417984f6e93da3af27466b768」はフォームごとに異なるので再設定が必要です。「応答の詳細を取得する」アクションの出力結果のJsonから添付ファイルのIDになります。

こちらの記事で詳細を解説されています。参考に確認して設定してください。

JSON の解析-添付ファイル

添付ファイルがある場合、Jsonの解析で値が扱えるようにします。

コンテンツには先程の条件で空白かどうかを確認した「@{outputs(‘応答の詳細を取得する’)?[‘body/r3604874417984f6e93da3af27466b768’]}」を設定します。

コピーしました!

Jsonスキーマ
{ "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string" }, "link": { "type": "string" }, "id": { "type": "string" }, "type": {}, "size": { "type": "integer" }, "referenceId": { "type": "string" }, "driveId": { "type": "string" }, "status": { "type": "integer" }, "uploadSessionUrl": {} }, "required": [ "name", "link", "id", "type", "size", "referenceId", "driveId", "status", "uploadSessionUrl" ] }
}

共有リンクの作成(個人のFormsの場合)

共有リンクを作成し、Teamsに投稿する用に整形しますが、個人のFormsかグループフォームかで処理が異なります。先ほどの「JSON の解析-添付ファイル」の繰り返し処理を行い全ての添付ファイルの共有URLを作成し、文字列変数に追加していきます。

共有リンクを作成する

個人のFormsの場合、個人のOneDriveに添付ファイルは保存されます。そのためアクションもOneDriveのものを利用します。

ファイルにはJSON の解析で取得したidを設定します。リンクの種類やリンクスコープは適宜設定してください。上記の場合、リンクを知っている人全員に閲覧のみの共有リンクの作成となります。

共有リンクの作成(グループフォームの場合)

グループフォームの場合は手順が異なります。パスから添付ファイルの情報を取得し、そこから共有リンクを作成しています。

パスによるファイル メタデータの取得

グループフォームの場合、「TeamsチームのSPO > ドキュメント(もしくはShared Document)> アプリ > Microsoft Forms > フォーム名のフォルダ」に添付ファイルがアップロードされるので、ファイルパスを途中まで手動で設定し、パスの最後のファイル名はJsonの解析で取得したファイル名を設定します。

ファイルまたはフォルダーの共有リンクの作成

「パスによるファイル メタデータの取得」で取得したIDをもとに共有リンクを作成します。

文字列変数に追加

取得したリンクやファイル名を文字列変数に追加します。最終的にアダプティブカードとして投稿するため、Json形式にしています。ファイル名とファイルURLを設定しています。

コピーしました!

Value
{ "type": "TextBlock", "text": "[@{items('For_each')['name']}](@{outputs('共有リンクを作成する')?['body/WebUrl']})", "wrap": true
},

アダプティブカードではURLは「[ファイル名](URL)」の形式にすることで、リンクとして投稿ができます。

この記事で紹介している画像などはOneDriveのものですが、SharePointの場合も同様に設定します。

作成

ここでは先ほどの「文字列変数に追加」のJsonを調整します。先程の状態では最後の「}」の後にカンマ「,」がある状態になります。Jsonとして正しくない形の為、最後の「,」のみ取り除きます。

ifなどを使い末尾が「,」で終わっているかを判定し、

  • 末尾がカンマならば、そのカンマを取り除いた文字列を返し
  • そうでなければ 元の文字列をそのまま返す

という処理をします。

入力するコードはこちらです。

コピーしました!

入力
if( equals( substring( variables('fileUrlText'), sub(length(variables('fileUrlText')), 1), 1 ), ',' ), substring( variables('fileUrlText'), 0, sub(length(variables('fileUrlText')), 1) ), variables('fileUrlText')
)

チャットやチャネルにカードを投稿する-チャネル通知

これまで取得や整形したデータをアダプティブカードとしてTemasのチャネルへ投稿します。チームとチャネルには変数を設定し、アダプティブカード部分には下記を設定しています。

コピーしました!

アダプティブカード
{ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.3", "body": [ { "type": "TextBlock", "text": "依頼者:@{body('ユーザーの検索_(V2)')?['value'][0]?['displayName']}", "weight": "Bolder", "size": "Medium" }, { "type": "TextBlock", "text": "依頼内容:@{outputs('応答の詳細を取得する')?['body/r9c1bbee18440475a8e6b0d4f521530f6']}", "weight": "Bolder", "size": "Medium" }, { "type": "Container", "items": [@{outputs('作成')} ] } ]
}

チャットやチャネルにカードを投稿する-登録者通知

Formsに投稿した人にも通知を送っていますが、アダプティブカードの内容はほぼ同じです。添付ファイルのURLもそのまま流用できます。

参考記事など

]]>
https://www.fulogabc.net/entry/forms-inquiries-with-multiple-attachment-links/feed0
【Power Apps】TeamsのチームIDとチャネルIDを確認するPower Appsアプリhttps://www.fulogabc.net/entry/power-apps-teamsid-confirmationhttps://www.fulogabc.net/entry/power-apps-teamsid-confirmation#respondSun, 13 Jul 2025 01:15:00 +0000https://www.fulogabc.net/?p=3477

Power AutomateでTeamsへ通知先を動的に設定したい場合際など、チームID等を取得したいケースが度々あります。いちいちURL等から確認することが面倒になり、Power Appsのアプリから確認できるようにし ... ]]>

Power AutomateでTeamsへ通知先を動的に設定したい場合際など、チームID等を取得したいケースが度々あります。いちいちURL等から確認することが面倒になり、Power Appsのアプリから確認できるようにしました。

このアプリを部署内で共有することで、ID等の確認が簡単になりPower AppsやPower Automateの作成の時短にも繋がります。

アプリ・ダウンロード

アプリはGitHubに公開しています。下記URLからダウンロードしてご利用いただけます。

機能など

実際のアプリ画面はこちら

Power AppsやPower Automateを作る方向けのアプリのため、デザインは凝らず、最低限の機能としています。

画面の左側では、チームの名前とIDが確認できるようにしています。「コピー」ボタンを選択することで、チーム名とIDがコピーできます。ドキュメントへ貼り付けたり、フロー作成の際にチームIDが必要な場合に利用できます。

画面の右側では、左側で選択したチームのチャネルの情報が表示されます。チャネル名とチャネルIDが確認でき、「コピー」ボタンを選択することで、チャネル名とIDがコピーできます。

]]>
https://www.fulogabc.net/entry/power-apps-teamsid-confirmation/feed0
【Power Apps】現在地の住所を取得する方法(Google Geocoding API)https://www.fulogabc.net/entry/power-apps-get-location-google-geocoding-apihttps://www.fulogabc.net/entry/power-apps-get-location-google-geocoding-api#respondTue, 08 Apr 2025 13:01:45 +0000https://www.fulogabc.net/?p=3405

Power Appsで現在地を取得し、その現在地の住所を取得する方法を紹介します。 今回のアプリはGoogle Cloud Platform(GCP)のGoogle Geocoding APIを利用します。 詳細は公式の ... ]]>

Power Appsで現在地を取得し、その現在地の住所を取得する方法を紹介します。

Google Maps Geocoding API の有効化と API キー取得

今回のアプリはGoogle Cloud Platform(GCP)のGoogle Geocoding APIを利用します。

詳細は公式のドキュメントに沿ってAPIを取得してください。

Power Apps・Power Automateの実装

アプリ画面

今回のアプリの完成イメージです。

Power Appsで現在地の緯度・経度を取得し、Power AutomateでHTTPアクションでAPIを実行し、住所を取得する方法で現在地の住所を取得します。

現在地の取得

Power AppsでLocation関数を使うことで、現在の緯度・経度を取得できます。ボタンのOnSelectなどに設定して取得します。

コピーしました!

Power Apps
Set(LocatiionDataIdo,Location.Latitude);
Set(LocatiionDataKeido,Location.Longitude);

この位置情報の取得はGPSだけでなくネットワークのIPアドレス等からもデータの取得を行います。そのため、GPSがOFFの端末などでは、正しくない位置情報が取得されることもあります。

API用のURIを作成する

Google Geocoding APIをPower Automateで実行してデータを取得しますが、Power AutomateのHTTPアクションで使うURIの値をPower Apps側ですべて作成します。

Google Geocoding APIで緯度・経度から住所を取得するには下記のURIの形式にする必要があります。これをPower Apps側で作成し、Power Automateに渡します。

コピーしました!

Google Geocoding API URI
https://maps.googleapis.com/maps/api/geocode/json?latlng={緯度},{経度}&key={API_KEY}

緯度・経度はSet変数でグローバル変数に格納しましたが、下ではテキストボックスの値を取得するようにしています。デバックで色んな緯度・経度で試す際に手入力できると便利でした。

コピーしました!

Power Apps
//Google Geocoding APIキーを入力
Set(ApiKey,"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
//Power AutomateのHTTPアクションのURIを設定
Set(apiUri, "https://maps.googleapis.com/maps/api/geocode/json?latlng="
& txt_ido1.Text & "," & txt_keido1.Text & "&key=" & ApiKey);

Power Automateで住所を取得する

今回作成するフロー全体図はこちら。

Power AppsからHTTP実行用のURIを取得し、データを加工してPower Appsに返すフローです。途中でデータを加工していますが、APIで取得するデータが多すぎるため、必要そうな部分のみに削っています。

Power Appsからデータを受け取るためにPower Apps (V2)で、下記のように取得する値を設定します。今回はPower Appsで作成したURIを受け取るための値として「apiUrl」を設定します。

HTTPアクションでURIにPower Appsから取得した値を設定します。

HTTPで取得した値をJSON の解析で使えるようにします。

コンテンツ
@{body('HTTP')?['results']} 

スキーマ
{ "type": "array", "items": { "type": "object", "properties": { "address_components": { "type": "array", "items": { "type": "object", "properties": { "long_name": { "type": "string" }, "short_name": { "type": "string" }, "types": { "type": "array", "items": { "type": "string" } } }, "required": [ "long_name", "short_name", "types" ] } }, "formatted_address": { "type": "string" }, "geometry": { "type": "object", "properties": { "location": { "type": "object", "properties": { "lat": { "type": "number" }, "lng": { "type": "number" } } }, "location_type": { "type": "string" }, "viewport": { "type": "object", "properties": { "northeast": { "type": "object", "properties": { "lat": { "type": "number" }, "lng": { "type": "number" } } }, "southwest": { "type": "object", "properties": { "lat": { "type": "number" }, "lng": { "type": "number" } } } } } } }, "navigation_points": { "type": "array", "items": { "type": "object", "properties": { "location": { "type": "object", "properties": { "latitude": { "type": "number" }, "longitude": { "type": "number" } } } }, "required": [ "location" ] } }, "place_id": { "type": "string" }, "plus_code": { "type": "object", "properties": { "compound_code": { "type": "string" }, "global_code": { "type": "string" } } }, "types": { "type": "array", "items": { "type": "string" } } }, "required": [ "address_components", "formatted_address", "geometry", "place_id", "types" ] }
}

選択アクションで必要なデータに絞ります。

開始
@{body('JSON_の解析')}

マップ
{ "long_name": @{item()['address_components']?[0]?['long_name']}, "short_name": @{item()['address_components']?[0]?['short_name']}, "type": @{join(item()['types'],',')}
}

選択アクションで取得したデータを文字列として変数に格納し、Power Appsへ返します。

Power Appsでフローを実行する

Power Appsでフローを実行し、Jsonをテーブルに変換します。コピーしました!

Power Apps
//フロー実行 UpdateContext({_GoogleGeoodingApiResult:GoogleGeoodingApi.Run(apiUri).apiresponsebody}); //実行結果をテーブルへ変換 UpdateContext( { GoogleGeoodingApiResult: ForAll( Table(ParseJSON(_GoogleGeoodingApiResult)), { long_name:Text(ThisRecord.Value.long_name), short_name:Text(ThisRecord.Value.short_name), type:Text(ThisRecord.Value.type) } ) } ); 

取得したデータはGoogleGeoodingApiResultに格納しています。

アプリ・フローダウンロード

GitHubに公開しています。下記よりダウンロードしてご利用ください。

参考記事など

]]>
https://www.fulogabc.net/entry/power-apps-get-location-google-geocoding-api/feed0