事務所移転のお知らせ

この度、当社は、下記の住所へ事務所を移転しました。

 〒 731-3168

  広島県広島市安佐南区伴南1丁目40-1 

  NEC 広島西風新都システムセンター 5階

既に、2023年8月25日(金)より業務を開始させていただいております。

これからも、よろしくお願い申し上げます。

とても環境のよい所です!すこし写真で紹介しますね。

入力規則のススメ~ユーザのライセンス種別で制限してみよう~

はじめに

こんにちは!株式会社オプトプランニングです。
Salesforce(Salesforce.com/セールスフォース・ドットコム、略してSFDC)であれこれやってみたことを書いていきます。

今回は入力規則について書いていこうと思います。
プロファイル・ユーザ・ロールの入力規則例は公式ヘルプに紹介されているので、ユーザのライセンス種別で制限する方法を紹介します。
こんなやり方もあるんだ~と参考になれば幸いです。

実際あった入力規則の盲点

入力規則を作成する際、プロファイルで制限する方法をよく見かけるため、最初はプロファイルで入力規則を作成していました。

その後、カスタムプロファイルを増やすために、影響調査を行う過程で「プロファイルを増やす=既存の入力規則の確認・修正・再テストが必要」なことに気づきました。

また、私が扱っている環境では複数のユーザライセンスが混在しおり、プロファイルではなくユーザのライセンス種別で入力規則を作成できるのではないかと気づきました。

今回紹介するユーザのライセンス種別で制限する入力規則は、単一のライセンスのみを使用している環境では利用機会がないかもしれないです。。。

ライセンス種別で入力規則を作るには

プロファイルで制限する場合、よく見かけるのがプロファイルの名前である「Profile.Name」を使用する例です。
ライセンス種別で制限する場合は、「UserType」を使用します。

ライセンス種別は、ユーザに割り当てられたライセンス種別を意味する「User.UserType」、ユーザに割り当てたプロファイルで指定しているライセンス種別を意味する「Profile.UserType」二つありますが、今回は「User.UserType」を使用する方法を紹介します。

「User.UserType」を「項目の挿入」を使用して入力する場合は、図1のように選択します。

図1 項目の挿入
図1 項目の挿入

SFDCでは様々なユーザライセンスがあるので、ライセンス種別に関して説明は割愛しますが、今回使用するライセンス種別と「UserType」名は以下です。

ライセンス種別 の名称UserType の名称
標準ユーザStandard

他の「UserType」について詳しく知りたい方はこちらを参考にしてください。

ライセンスで制限する入力規則を作ってみた

ライセンスで制限する入力規則を実際に作成してみようと思います。
環境はTrailhead、オブジェクトは「取引先」を使用し、入力規則の作成やレコードの新規登録は「標準ユーザ」ライセンスを持つユーザで行います!

まずは、以下のような2つの入力規則を作ってみます。

  • 項目「評価」を未選択で保存するとエラーが発生し、項目「評価」にエラーメッセージを表示
  • 項目「会社形態」を未選択で保存するとエラーが発生し、項目「会社形態」にエラーメッセージを表示

エラー条件数式は以下です。
「[数式 サンプル] 入力規則により項目の入力を必須とする数式」で紹介されているサンプル数式を活用しました)

ISPICKVAL(Rating , '')
ISPICKVAL(Ownership , '')

その他の設定については図2を参照してください。
エラー条件式とエラー表示場所以外は項目「会社形態」の設定も同様なので割愛します。

この入力規則を有効化して、取引先を新規登録しようとすると図3のようなエラーが表示されます。
(必須項目が未入力状態だと入力規則の判定はされないので、必須項目に適当な文字列を入力しています)

図2 項目「評価」の入力規則
図2 項目「評価」の入力規則
図3 入力規則で項目「評価」「会社形態」でエラー発生
図3 入力規則で項目「評価」「会社形態」でエラー発生

先ほど作成した入力規則の確認ができたところで、項目「評価」の入力規則を以下のように変更してみようと思います。

  • ライセンス種別が「標準ユーザ」以外のユーザが項目「評価」を未選択で保存するとエラーが発生し、項目「評価」にエラーメッセージを表示

変更後のエラー条件式は以下です。

AND(
ISPICKVAL(Rating , '') ,
NOT(ISPICKVAL( $User.UserType , 'Standard'))
)

「UserType」のデータ型は選択リスト型である点は注意が必要です。
「Profile.Name」のデータ型はテキスト型なので、演算子での比較が可能ですが、「UserType」のデータ型は選択リスト型なのでこのままでは比較ができず「ISPICKVAL()」関数を使用してデータを比較する必要があります。
「ISPICKVAL()」の詳細はこちらを参照してください。

図4が項目「評価」の入力規則変更後です。

入力規則を変更後、取引先を新規登録しようとすると図5のようなエラーが表示されます。

ライセンス種別が「標準ユーザ」のユーザは、項目「評価」を未入力でも入力規則にひっかからないことが分かります。

無事にライセンス種別で制限する入力規則ができました!!

図4 ライセンス種別で制限した入力規則例
図4 ライセンス種別で制限した入力規則例
図5 入力規則で「会社形態」のみエラー
図5 入力規則で「会社形態」のみエラー

あとがき

Salesforceではライセンス種別がたくさん用意されているので、お使いの環境下でどんなライセンス種別があるか知っておくといいかもしれません!

また、入力規則を作成する際はライセンスで制限をかける場合もプロファイルで制限をかける場合も、作りたい入力規則が誰に対して制限したいものなのかを明確にしておくといいと思います。

今回はユーザのライセンス種別での制限方法を紹介しましたが、ロールを使用する方法などを含め、プロファイル以外で制限をする方法も知っておくといいと思います。

それでは、またお会いしましょう!!

社内 野の花画伯から 里山の花々

全国的に暑くなってまいりましたね。
久しぶりに、社内 野の花画伯から、新作の絵が届きました。

「里山の花々」です。

ササユリ、アザミ、撫子、アカマンマ、ツユクサ、リンドウなどなど。

どれも身近に咲いている花々たちですが、1枚の紙に描かれることで、
それぞれの色合いや形が引き立ち、華やかな雰囲気を醸し出しています。

花の1つ、「アカマンマ」という花ですが、別名「イヌタデ」というそうです。
タデ科の一年草で日本全土、アジアに広く分布しています。
みなさまの身近にも咲いているかもしれませんね。

アカマンマの由来は、粒上の赤紫色の花を赤飯の粒にみたて、
こどもたちが、ままごとに使ったことからだそうです。

画面下中央のテントウムシが、良い表情だと思いませんか?!

出典 小学館 日本大百科全書(ニッポニカ)日本大百科全書(ニッポニカ)について

AWS ECSサービスを構築しよう(その2)

ECSサービス構築の二回目です。前回は,ECRに登録するdockerイメージをコンテナから作成するところまででした。今回は,ECRリポジトリーに登録,ECSサービスの構築手順です。
            図A 利用するAWSリソースと構成図

1. ECRにリポジトリ作成

作成したコンテナイメージを、コンテナレジストリのフルマネージドサービスである Amazon Elastic Container Registry (Amazon ECR) にアップロード(Push)します。
作成したコンテナイメージを、コンテナレジストリで一元管理することで、様々なコンテナ実行環境で利用しやすくなるメリットがあります。AWS コンソールにログインして,ECRリポジトリを作成します。
引用url ECRとは
               図B リポジトリ作成
このuriをコピーして,メモしておきます。後で、イメージのtag付けに必要になります。

1.2. EC2クライアントからECRにログインする

EC2クライアントから,ECRにpushする為に,ECRにログインする必要があります。ログイン用のスクリプトを作成します(login.sh)。そのスクリプトを利用してECRにログインします。
参照した URL AWS ECRにdockerイメージを登録する
aws ecr get-login --no-include-email --region ap-northeast-1 > login.sh ←一行です
[ec2-user@ip-10-128-1-19 ECR]$ bash ./login.sh
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/ec2-user/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded ← これが出ればログイン成功
前回作成したイメージから,ECR登録用のイメージtagを作成します。先ほど,コピーしておいた,uriが必要になります。
(123456789012はアカウントID)
docker tag redminesql:latest \
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/redmine6:latest
ECRにイメージをpushします
(123456789012はアカウントID)
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/redmine6:latest ← 一行です
これで,ECRのリポジトリにdockerイメージの登録が完了しました。
図AのECR Registoryです。

2. ECSサービスの構築

ECSサービスの構築は,ECSクラスターの作成,タスクの定義,サービスの作成という手順で行います。

2.1 ECSクラスターの作成

ECS クラスターは、コンテナを動かすための論理的なグループです。ECS を操作するために、まずは ECS クラスターを作成します。AWSコンソールから,クラスターの作成を行います。
ecs→クラスターの作成をクリックします。設定内容は,クラスター名,実行するVPC,サブネットです。
引用url ECSクラスターの作成
            図C ECSクラスターの作成1
              図D ECSクラスターの作成2

2.2. タスク定義

タスク定義とは、アプリケーションを動かすために、どのようにコンテナを動かすか、コンテナの動作を定義したものです。 例えば、コンテナイメージの種類、アプリケーションが利用するポート、コンテナが利用するデータボリュームなどを指定できます。
コンテナを動かす際のブループリントとして機能します。タスク定義をawsコンソールから行います。設定内容は,タスク定義名,ECRのuri,コンテナのlistenポート番号,動作させるサーバ(今回はFargate)です。
引用 URL タスク定義
              図E タスク定義1
              図F タスク定義2
              図G タスク定義3
              図H タスク定義4

2.3. サービスの作成

サービスとは、ECS 上でコンテナを動かすときに利用する概念の一つです。
サービスを使用すると、 Amazon ECS クラスターで、指定した数のコンテナ群(タスク)を維持できます。作成するサービスの定義をします。設定内容は,タスク定義の選択,サービス名,実行するVPC,サブネット,セキュリティグループ,ALBです。
引用url サービスとは
              図I サービス作成1
              図J サービス作成2
              図K サービス作成3
              図L サービス作成4
              図M サービス作成5
                 図N サービス作成6

3.サービスの実行

サービスの作成に成功したら,サービスを実行します。作成したサービスを選択する。ネットワーキングをクリック。オープンアドレス(ALBのアドレス)をクリックです。
              図O サービスの実行1
              図P サービスの実行2
              図Q サービスの実行3
              図R サービスの実行4
ALB経由で,Fargateコンテナのredmineログイン画面が出れば作成完了です。

AWS ECSサービスを構築しよう(その1)

Redmine4.2と,依存関係でDBが必要なので,mariaDB(10.11.2)(MySQL系)2つのdockerコンテナを作成します。Redmineコンテナ起動後にwebhookというpluginをインストール,更にDBをRDS(mySQL)に変更後,作成したコンテナからイメージを作成し,ECRに登録します。そのイメージからECSサービスをデプロイします。今回は,ECRに登録するイメージを作成するまでの手順です。

1. 利用するAWSのリソースと作成するシステム構成図

             図A システム構成図

2. Docker環境構築

EC2(図AのDockerコンテナ)にdocker,docker-composeをインストールして,dockerが動作する環境を構築します。
#Dockerのインストール
sudo yum install -y docker
sudo systemctl start docker
sudo usermod -a -G docker ec2-user
#自動起動を有効にする
sudo systemctl enable docker
#docker-composeのインストール
sudo curl -L https://github.com/docker/compose/releases/download/1.28.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose  ←一行です
sudo chmod +x /usr/local/bin/docker-compose

#Docker Composeが使用できるか確認
/usr/local/bin/docker-compose --version
docker-compose version 1.28.5, build c4eb3a1f

コマンド docker ps とすると以下のメッセージ出力
#Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containe
rs/json": dial unix /var/run/docker.sock: connect: permission denied
###対策 dockerグループにec2-userを追加
sudo usermod -g docker ec2-user

3. docker-compose.ymlファイルを作成して、docker コンテナを作成

作成するコンテナの設計図ですね。今回は,redmineとそのDBのコンテナを作成して,webhookというPluginを入れ、更にDBをRDS(Mysql)に変更します。
version: '3.8'
services:
  redmine:
    image: redmine:4.2
    container_name: redmine
    ports:
      - 80:3000
    environment:
      REDMINE_DB_MYSQL: redmine-db
      REDMINE_DB_PASSWORD: xxxxxx
    depends_on:
      - redmine-db
    restart: always

  redmine-db:
    image: mariadb
    container_name: redmine-db
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD: xxxxxx
      MYSQL_DATABASE: redmine
    volumes:
      - ./data/db:/var/lib/mysql
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    restart: always

4. Docker コンテナの作成と起動

docker-compose.ymlファイルのあるディレクトリで以下のコマンドを実行します。完了したら,docker ps -a コマンドで動作しているかどうか確認します。
sudo su
cd /usr/local/src/redmine
/usr/local/bin/docker-compose  up -d
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                                       NAMES
9e7f0be2bc5b   redmine:4.2   "/docker-entrypoint.…"   7 seconds ago   Up 5 seconds   0.0.0.0:80->3000/tcp, :::80->3000/tcp       redmine
3cd27d886b4f   mariadb       "docker-entrypoint.s…"   8 seconds ago   Up 6 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp   redmine-db

docker コンテナが作成されて起動されているのがわかります。Webでアクセスして確認しましょう。アドレスは、EC2のグローバルアドレスです。http://xx.xx.xx.xx/ログイン出来ればOKです。
               図B redmineログイン画面

5. webhook pluginをコンテナにインストール

作成したコンテナ(図AのDockerコンテナ)にwebhookというpluginをインストールします。
#Docker コンテナの中に入ります
docker container exec -it redmine bash
# pluginsディレクトリに移ります
root@f3baf480c406:/usr/src/redmine# cd plugins/
root@f3baf480c406:/usr/src/redmine/plugins# git clone https://github.com/suer/redmine_webhook.git ← 一行
root@f3baf480c406:/usr/src/redmine/plugins#  cd redmine_webhook
root@f3baf480c406:/usr/src/redmine/plugins/redmine_webhook# bundle install
rake redmine:plugins:migrate RAILS_ENV=production
#docker コンテナから抜けます
root@f3baf480c406:/usr/src/redmine/plugins/redmine_webhook# exit

redmine コンテナを再起動します。
docker stop redmine
docker start redmine
ブラウザでアクセスして、管理タブをクリックプラグインが表示されればOKです。
            図C webhook pluginインストール後

6. RDSと接続

privateサブネットに作成したRDS(Mysql)に接続させるように変更していきます。
#database接続定義(database.yml)の作成

production:
  adapter: "mysql2"
  host: "databasexxx.xxxxxx.ap-northeast-1.rds.amazonaws.com"
  port: "3306"
  username: "Admin"
  password: "xxxxxx"
  database: "redmine_db"

database.ymlをdockerコンテナ内にコピー
sudo docker cp database.yml redmine:/usr/src/redmine/config/

#redmine  migrate実行
#docker コンテナ内部に入ります
docker container exec -it redmine bash
/usr/src/redmin/# bundle exec rake generate_secret_token
/usr/src/redmine# bundle exec rake db:migrate RAILS_ENV=production
これで,ECSサービスとして起動可能なredmineコンテナが作成できました。
このコンテナを利用してECRに登録するimageを作成します。

7. ECR登録用のイメージ作成

作成したDockerコンテナからECRに登録するイメージを作成します。
#コンテナからイメージの作成
$ docker commit redmine redminesql

#イメージの確認
$ docker images
REPOSITORY        TAG       IMAGE ID       CREATED         SIZE
redminesql        latest    304ab9ccde49   8 seconds ago   554MB
fortune-whale     latest    0df1bdab20e2   2 days ago      280MB
redmine           4.2       d4ea63462562   2 days ago      531MB
mariadb           latest    4a632f970181   2 weeks ago     401MB
docker/whalesay   latest    6b362a9f73eb   7 years ago     247MB
これで登録するdockerのイメージが作成できました。次回は、ECRにログインしてimageの登録,ECSのデプロイ,ECSタスクの実行する手順です。

外部メール送信をフローでやってみた

はじめに

こんにちは!株式会社オプトプランニングです。
Salesforce(Salesforce.com/セールスフォース・ドットコム、略してSFDC)であれこれやってみたことを書いていきます。

Apexを使った簡単なメール送信方法は以前ご紹介しましたが、今回はフローを使ったメール送信方法について書いていきたいと思います!!

今回はTrailheadでフローを作成しています。

外部メール送信をフローの新規作成からやってみた

設定からフローの新規作成をしてみよう

早速、フローを作っていきたいと思います。

まず、設定のホーム左上にある検索に「フロー」または「flow」と入力し、「プロセスの自動化」の配下にある「フロー」をクリックします。
(検索は、実は英語名でヒットするものもあります。今回の「フロー」と「flow」の検索結果の違いなど、気になった方は試してみて下さい。画像は「flow」で検索しました)

フローの一覧が表示され、右上に「新規フロー」というボタンがあるので、クリックします。

図1 フロー新規作成
図1 フロー新規作成

フローの起動条件を選んでみよう

新規フロー画面が立ち上がるので、フローの起動条件を選び、右下の「作成」をクリックします。

今回は、「画面フロー」で作ってみようと思います!


図2 新規フローの起動条件選択
図2 新規フローの起動条件選択

フロー要素を追加してみよう

起動条件を選んだら、メール送信の要素を追加します。
要素の追加は「+」をクリックします。

「+」をクリックすると、どの要素にするか選択画面になるので、「アクション」をクリックします。

要素「アクション」のヘルプテキストに

フローの外部のアクション(メールの送信や承認申請など)を実行します。

と書いてあるのでわかりやすいですね!
(少し前までこのようなヘルプテキストはなかったように思います。最近のフロー移行の流れから、よりわかりやすいフロー作成のためかもしれないですね)

図3 要素の追加「+」部分
図3 要素の追加「+」部分
図4 要素の「アクション」
図4 要素の「アクション」

もし、フローを作成しようとしている環境でメールアラートを設定している場合は、要素の内容に「メールアラートを送信」というものがあるので、間違えて選択しないようにしましょう。

図5 メールアラート設定済みの場合
図5 メールアラート設定済みの場合

アクションを選んでみよう

要素で「アクション」を選んだら、次はアクション内容の選択を行います。

新規アクション選択画面が表示されるので、真ん中の検索に「メール」と入力します。

すると、「メールを送信(emailSimple-emailSimple)」という項目が検索窓の下に表示されるのでクリックします。

図6 アクション「メールを送信」
図6 アクション「メールを送信」

外部に送信するメールの設定をしよう

アクションで「メール送信」を選んだら、外部へ送信するメールの設定画面が表示されます。

この時、入力必須のものは

  • アクションの表示ラベル
  • アクションのAPI参照名
  • メールの件名
  • メールの本文

です。
それ以外は任意項目となっており、任意項目は項目横のトグルボタンをクリックすると入力欄が出現します。

図7 メール送信に必須項目
図7 メール送信に必須項目
図8 任意項目の入力欄
図8 任意項目の入力欄

必要事項の入力が出来たら「完了」をクリックします。

これで外部メール送信が完成しました!!

図9 外部メール送信フロー完成
図9 外部メール送信フロー完成

フローを保存しよう

このままブラウザを閉じてしまうとせっかく作成したフローがなくなってしまうので、右上の「保存」ボタンを押して、フローの保存を行います。

図10 フローの保存
図10 フローの保存

保存しようとすると、フローの表示ラベル、API参照名の入力画面が表示されるので、それぞれ入力して保存しましょう。

おわりに

ざっとではありますが、フローで外部メール送信を作ってみました。

今回は説明できなかったですが、フローの起動条件をレコードトリガフローにしてみたり、メールテンプレートを作成してみたりすると件名や本文を動的なテキストにすることができるので幅が広がります。

テンプレートについても近いうちにやってみたで紹介できればと思います。

それでは、またお会いしましょう!!

社内 野の花画伯から 万年青(おもと)

あけましておめでとうございます。
本年もどうぞよろしくお願いいたします!

社内 野の花画伯から、新年の絵が届きました。

万年青(おもと)です。

花言葉は「長寿」、「長命」が代表的です。

理由は、一年中葉が緑で、冬も枯れず、何十年も育つのでこの花言葉がついたそうですよ!

昔から非常に縁起が良いものとされていますね。
邪気を払い、運気が開けるとも言われています。

お祝いのシチュエーションでは、「お祝い万年青」としても重宝されます。
開院、開業、結婚、お正月などの慶事に良く飾られています。

お正月に赤い実がなり、葉である母が子である実を守るように育つため、
母性の愛など崇高な精神と子孫繁栄も象徴されます。

徳川家康が江戸城に入る時、3鉢の万年青を贈られたという話も有名ですね!
その後、徳川家は300年も栄えたことから、大変縁起が良いとされています。

レポートの期間集計やってみた

はじめに

こんにちは!株式会社オプトプランニングです。
Salesforce(Salesforce.com/セールスフォース・ドットコム、略してSFDC)であれこれやってみたことを書いていきます。

レポートを作成していると「過去の月ごとの商談件数が知りたい」や「月ごと・週ごとの金額の合計がわかればいいな」など、データを期間ごとに集計したい場面は多いと思います。

そんな時に使うのが、「期間集計」です。

これは、データ型が「日付」「日付/時間」項目の場合、簡単な設定で任意の期間で集計をすることができるものです。

今回はLightning Experienceでの期間集計の方法や、やってみて分かったこと、他の方法などを書いていきたいと思います。

※2023/1/30 訂正・追記あり

日付項目を年月(YYYYMM月)で期間集計してみた

早速、期間集計をやってみようと思います!

今回使用するレポートは、以前のブログでも使用したTrailheadのモジュールをダウンロードした時に入っていた図1のレポートです。
(どのモジュールだったかは前回から思い出せておりませんのであしからず)

まずは、右上の「編集」をクリックしてレポートの編集画面を表示させます。

図1 使用レポートの編集
図1 使用レポートの編集

今回は、レポート内にある「完了予定日」を期間集計してみたいと思います。
日付項目を期間集計するには、対象の項目がグループ化された行または列に存在する必要があります。

列にある項目「完了予定日」を期間集計しようとしてみても、以下のように期間集計できる項目が出てきません。

図2 「完了予定日」グループ化前
図2 「完了予定日」グループ化前

そこで、「完了予定日」を行グループに移動して期間集計しようとすると…
「集計期間単位」という項目が出てきました!

期間集計は、この「集計期間単位」で任意の単位を選択することで設定します。

今回は「年月」で集計しようと思うので単位に「年月」を選択します。
(図3のようにデフォルトでは「日付」が選択されていますが「年月」をクリックすると選択できます)

図3 「完了予定日」グループ化後
図3 「完了予定日」グループ化後

すると、日にちまで表示されていた「完了予定日」が年月のみの表示に変わりました!

図4 「完了予定日」を「年月」単位で期間集計
図4 「完了予定日」を「年月」単位で期間集計

編集時は表示されるデータが少ないため、期間集計で何が変化するのかわかりにくいですが、期間集計する前後のレポートを見比べてみると以下のようになります。

左図が「完了予定日」を期間集計する前、右図が「完了予定日」を期間集計した後です。
(わかりやすくするため、基準とグラフ種類を変更しています。)

図5 期間集計前
図5 期間集計前
図6 期間集計後
図6 期間集計後

期間集計前は日ごとに集計されていたのが、「年月」で期間集計したことで月ごとに集計されるようになりました。

オブジェクトの項目を増やしたりすることなくこのような集計が行えるのはとても便利ですね!

実際にやってみてわかったことや気をつけたいこと

期間集計はあくまで集計するための機能

期間集計を行う場合、対象の項目がグループ化されていなければなりません。
期間集計が表示されない場合は、対象の項目をグループ化しているかどうか確認してみましょう。

あくまで「集計」機能なので、データの表示形式を変更するためのものではないということを念頭に入れておきましょう。

また、期間集計を行う項目はグループ化しなければならないため、表形式のレポートでは使用できません

期間集計を行った項目の表示内容

期間集計を行った項目は、期間集計で選択した単位でしか表示されなくなります。

今回やってみた期間集計を例にすると、「完了予定日」を「年月」で期間集計したレポートは、完了予定日の年月だけ表示され、完了予定日の日付は表示されません

集計は「年月」で行いたいけど、日付や時間などの表示もレポートに表示したいのに…という時は気をつけたい部分です。

データ内容は変わらないので、表示されていない情報(例で言えば「完了予定日」の日付)はレコードを参照すればいいのですが、いちいちレコードを参照するのも面倒に感じてしまいます。
期間集計を行う項目は、期間集計後の表示でいいかの判断が必要かもしれません。

エクスポートをやってみてわかったこと

エクスポートをしてみると期間集計を行った項目に関して影響が出る場合があります。

「フォーマット済みレポート」の場合、期間集計を行う前後でエクスポートされるデータ内容が変わります

先ほどの期間集計した前後のレポートをエクスポートして比較すると以下のようになります。

図7 期間集計前後のレポートのエクスポート結果(フォーマット済みレポートの場合)
図7 期間集計前後のレポートのエクスポート結果(フォーマット済みレポートの場合)

「フォーマット済みレポート」でエクスポートした時、期間集計した項目はレポートで表示された内容のままエクスポートされます。

期間集計を「年月」で行ったレポートをエクスポートすると、エクスポートしたファイルでは「完了予定日」の日付は分からなくなってしまいます。

「詳細のみ」でエクスポートした場合は、期間集計を行う前後でデータ内容は変わりません

期間集計する前後のレポートをエクスポートした比較は以下です。

図8 期間集計前後のレポートのエクスポート結果(詳細のみの場合)
図8 期間集計前後のレポートのエクスポート結果(詳細のみの場合)

「詳細のみ」でエクスポートした時、期間集計した項目はレコードデータに基づいた内容でエクスポートされます。

期間集計を「年月」で行ったレポートでも、エクスポートしたファイルから「完了予定日」の日付がわかります。

期間集計を行いたいけど、項目の表示形式は変更したくない!!

行レベルの数式を使ってみよう

年月などの期間集計はやりたいけど、対象項目の表示形式はそのままにしておきたいという場合もあると思います。

また、エクスポートの結果からレポートの期間集計は使いにくいということもあるでしょう。

そんな時に私が思いついたのは、期間集計を行いたい項目を利用して「行レベルの数式」を作成し、その数式を集計項目に利用する方法です。

行レベルの数式を作ってみた

行レベルの数式もレポート編集画面から簡単に作成できます。

レポート編集画面を開いたら「列」の右にある「▼」をクリックすると「行レベルの数式を追加」があるのでクリックします。

図9 行レベルの数式を追加
図9 行レベルの数式を追加

「行レベルの数式列を編集」画面が開くので、以下のように設定します。

「列の名前」はレポートに表示される項目名になるので、必要があれば「説明」に数式の内容を書いておくといいと思います。

列の名前完了予定年月
数式出力種別テキスト
数式MID(TEXT(CLOSE_DATE),1,4) & ‘年’ & MID(TEXT(CLOSE_DATE),6,2) & ‘月’

この数式は「完了予定日」の年月部分だけをテキスト形式で表示させるものになります。
※2023/1/30数式訂正。詳細は追記を参照

図10 行レベルの数式列の編集画面

適用をクリックすると行レベルの数式が作成されているので、作成した数式でグルーピングを行います。
同時に、期間集計に使用していた「完了予定日」は列の方に戻してみます。

図11 数式をグルーピング
図11 数式でグルーピング
図12 数式で集計したレポートの表示
図12 数式で集計したレポート

すると、「完了予定日」の「年月」で集計しつつ、「完了予定日」の内容をレポート上に表示できるようになりました!!

ついでにエクスポートもしてみた

行レベルの数式があるレポートを「詳細のみ」でエクスポートしてみるとどうなるか試してみました。

すると…

図13 数式で集計したレポートのエクスポート結果
図13 数式で集計したレポートのエクスポート結果

行レベルの数式も項目としてデータをエクスポートできることが分かりました!!!

これだと、エクスポート後のデータの活用に幅が広がるかもしれませんね~

おわりに

期間集計ですが、実務の方ではLightning Experienceでの期間集計方法がわからず、苦肉の策として編み出したのが行レベルの数式を作成して集計をしてみることでした。

行レベルの数式を作成した後に期間集計の方法が分かったのですが、期間集計した項目の表示だと私が作成したいレポートでは表示内容が不十分なことが多く、そのまま行レベルの数式で集計を行うレポートもありました。

今回書くにあたって、エクスポートについてもいろいろ試してみてより理解が深まったので、この気づきを生かして利用者が使いやすいレポート作成を心掛けていきたいと思います!

それでは、またお会いしましょう!!

追記

2023/1/30、完了月が正しく並び替えできないという問題があるため数式を訂正しました。(初歩的なミスですみません)

当初の数式【 TEXT(YEAR(CLOSE_DATE)) & ‘年’ & TEXT(MONTH(CLOSE_DATE)) & ‘月’) 】と訂正後の数式【 MID(TEXT(CLOSE_DATE),1,4) & ‘年’ & MID(TEXT(CLOSE_DATE),6,2) & ‘月’ 】の「完了予定年月」の表示を忘備録として載せておきます。

追記1 当初の数式
追記1 当初の数式
追記2 訂正後の数式
追記2 訂正後の数式

訂正後の「完了予定年月」は正しく並び替えできています。

今回、参考にした数式は公式ヘルプに紹介されていました。

[数式 サンプル] 日付型項目から年・月を抽出する数式

AWS CLIで情報を出力しよう 色々編(Linux版その4)

1. AWS CLIコマンドのヴァージョンアップをしよう

$curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o "awscliv2.zip"
$unzip awscliv2.zip
$sudo ./aws/insstall --update
$aws --version
aws-cli/2.9.10 Python/3.9.11 Linux/5.10.157-139.675.amzn2.x86_64 exe/x86_64.amzn.2 prompt/off

2022/12/27 時点で最新バージョンです 詳しくは、以下を参照 AWS CLI 最新バージョンをインストールまたは更新する
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

2. 前回の復習 InternetGW情報を出力しよう

InternetGWの情報を必要な項目のみ出力してみよう

$aws ec2 describe-internet-gateways \
--query "InternetGateways[].[{VPC_id:Attachments[0].VpcId,Name:Tags[0].Value}]" --out table

             図 A InternetGWの情報

3. AWSが保持しているグルーバルアドレスCIDRを表示しよう

3.1 AWSが保持している東京リージョンのグローバルCIDRの表示

AWSが保持しているグルーバルアドレスのCIDRが公開されています。(json形式)その内容から東京リージョンのIPレンジのみを出力します。

$curl https://ip-ranges.amazonaws.com/ip-ranges.json | \
jq -r '.prefixes[] | select(.region=="ap-northeast-1") | .ip_prefix'

curl コマンドでjsonファイルを取ってきます。 jp コマンドでリストになっているprefix[]からreginがap-northeast-1(東京)のもので、ip_prefix項目のみ出力させます

jq コマンドは以下でインストールしてみてください

$sudo yum install jq

            図B 東京リージョンのIPアドレスレンジ

3.2AWSが保持している東京リージョンでEC2のグルーバルアドレスCIDRを表示

東京リージョンでEC2のIPレンジのみを出力します。

$curl https://ip-ranges.amazonaws.com/ip-ranges.json | \
jq -r '.prefixes[] | select(.service=="EC2" and .region=="ap-northeast-1") | .ip
_prefix'

curlコマンドでjsonファイルを取ってきます。jpコマンドでリストになっているprefix[]からreginがap-northeast-1(東京)かつ serviceがEC2のip_prefixのみを出力させます

           図C 東京リージョンEC2のIPアドレスレンジ

4. AWS Health イベントで使用されるサービス名の一覧を出力

HealthイベントをEventBridge経由で監視するイベントルールの対象を特定のサービスとする場合に、対象のサービス名は、”A2I”、”SSM”と選択可能である、これがなんのサービスかわかりたい

$aws health describe-event-types

             図D Health サービス名一覧

Health イベントで使用されるサービス名の一覧は、aws health describe-event-types コマンドで出力できます。json形式で出力されます。沢山出力されるのである程度絞り込みを行います。

$aws health describe-event-types | \
jq -r '.eventTypes[] | select(.service=="SSM" or .service=="A2I") | .code'

   図E Health A2IとSSMに絞り込み出力

Health イベントで使用されるサービス名の一覧は、aws health describe-event-types コマンドで出力できます。これでは、沢山出力されるので、対象を絞ります。 jqコマンドのselectを利用して SSMとA2Iに絞ります。そして、codeの部分のみを出力します。A2IはAmazon Augmented AI(AmazonA2I)のことだそうです。「A2I aws」で検索するとヒットします。

5. AWS WindowsのAMI一覧を出力しよう

Windows-serverのAMIはどのような物があるか、質問が良くあります。AWS CLIコマンドを使って出力できます。(Windows-server2019の例です)

$aws ec2 describe-images \
--owners amazon \
--filters "Name=name,Values=Windows_Server-2019-*" \
--query "sort_by(Images,&Name)[].[Name,ImageId]" \
--out table

           図F  windows-server-2019 AMI情報

imageは、aws ec2 describe-imageコマンドで出力します。filterオプションで windows_Server-2019-*のみを対象にします。更に、queryで ImagesNameとImageIdをsortして出力します。

6. routeテーブルを見て、publicサブネットかどうか判断しよう

publicサブネットかどうかは、routeテーブルを見ないとわかりません。ルートテーブルの(0.0.0.0/0)があるかどうかで判断できます。

$aws ec2 describe-route-tables \
--query "RouteTables[].{Sub:Associations[].SubnetId,Id:RouteTableId,rou:join('<->',Routes[].DestinationCidrBlock),INgw:Routes[].GatewayId}"\
--out text

            図G ルートテーブルと0.0.0.0/の関係

routeテーブルを出力します。queryで出力項目を絞り込みます。Associations[].SubnetIdとRouteTableId,join(‘<->’)で文字列を加え、Routes[].DestinationCidrBlock,Routes[].GatewayIdを出力します。<->0.0.0.0/0があるサブネットがpublicサブネットです。

Linux版その1 EC2の情報出力 https://opt-p.co.jp/blog/aws/post-1633/

Linux版その2 RDSの情報出力 https://opt-p.co.jp/blog/aws/post-1718/

Linux版その3 VPCの情報出力 https://opt-p.co.jp/blog/aws/post-2080/

Apexを使った1日に複数回動作させるバッチ処理

セールスフォース

 Salesforceでバッチ処理を作成する方法としてはフロー処理の中の「スケジュールトリガーフロー」を使ってフロー処理として記述することが可能ですが、フローを動作させる頻度が「1回のみ、毎日、毎週」しかなく、1時間ごとに動作させるような設定ができません。

 今回は、10分ごとに処理を行うための実装をApexを使って行います。

1.バッチクラスとスケジュールクラス

 スケジュールの開始はスケジュールクラスを継承したクラスで実施し、この中からバッチクラスを呼び出し、バッチを実行します。

1.1 バッチクラスの作成

 バッチクラスを実装するためにはバッチクラスをインプリメントする必要があります。

 public class xxxxBatch implements Database.Batchable<sObject>,Database.Stateful { ....

 また以下のメソッドを実装する必要があります。

  
/* バッチ処理開始時に最初に呼び出される。バッチ処理対象となるレコードを返却するQueryLocatorを返す。*/ 
public Database.QueryLocator start(Database.BatchableContext bc) {
       処理
       return Database.getQueryLocator(xxxxx);
}
/* バッチサイズで指定されたレコード数の単位で、呼び出される。*/
public void execute(Database.BatchableContext bc,List<sObject> executeRecords) {                   
       処理
}
/* バッチ処理の終了時に呼び出される。終了処理があれば実装する */
public void finish(Database.BatchableContext bc) {
       処理
}

 それぞれのメソッドの記述内容は以下の様になります。

 startメソッドでは、DBの情報を取得するためのQueryを作成しそれを返却します。

public Database.QueryLocator start(Database.BachableContext bc) {
           string query = 'select XXXX from YYYY';           return Database.getQuery(query);
}

 startメソッドの終了後、executeメソッドが呼び出されます。その際startの返却値であるQueryが実行され、その結果がexecuteメソッドの第二引数に渡され、executeメソッドが呼び出されます。
 executeメソッドでは主たる処理を記述します。

public void execute(Database.BatchableContext bc,List(sObject> executeRecords) {
       ......
       for(hoge xx : executeRecords) {
          .........
       }
       .......
}

 executeメソッドに引き渡されたQeryの実行結果を順に取り出して処理を実施します。
 executeメソッドでExceptionが発生した場合、このトランザクションで実行されたものがロールバックされてしまいます。そのため、この処理の中でメール送信などを行っている場合にはメールを送信する処理もトランザクションの一部となるためメールが送信されないことになります。
 そのためtry~catch()を使用してExceptionを捕まえて処理することが必要となります。
 最後にfinishメソッドが実行されます。今回はこのfinishメソッド中で次のスケジュールを設定します。

public void finish(Database.BatchableContext bc) {
       DateTime nextSchedTime = DateTime.now().addMinutes(10);
       xxxxBatchSchedule cls = new xxxxBactchSchedule();
       String nextJobName = 'xxxBatchSchedule_'+nextSchedTime.format('yyyyNNddHHmm');
       String schd = nextSchedTime.format('0 m H d M ? yyyy');
       System.schedule(nextJobName,schd,cls);
}

 スケジュール設定について簡単な説明を以下に記載します。

DateTime nextSchedTime = DateTime.now().addMinutes(10);

 次にバッチを起動する時間を設定しています。10分毎にバッチ処理を実施するため、現在時間にaddMinutes()メソッドをつかって10分を加算し、次にバッチ処理を起動する時間を算出しています。

  xxxxBatchSchedule cls = new xxxxBactchSchedule();

 次節で説明するスケジューラクラスをインスタンス化しています。

  String nextJobName = 'xxxBatchSchedule_'+nextSchedTime.format('yyyyNNddHHmm');
  String schd = nextSchedTime.format('0 m H d M ? yyyy');

System.scheduleメソッドに渡すための、スケジュール名と、スケジュール設定する時間を作成しています。スケジュール名は一意でないといけないので、スケジュール時間を付加しています。

System.schedule(nextJobName,schd,cls);

スケジュール設定を行っています。

1.2 スケジュールクラスの作成

 スケジュールクラスでは、Schedulableをimprementします。またスケジュール済のパスが同時に処理できるレコードの数を指定します。デフォルトおよび最大値は200となっています。

 バッチサイズについては分単位、バッチ処理、および制限の強化によるスケジュール済みパスのパワーアップを参照してください。

public class xxxxBactchSchedule imprements Schedulable{
       private final Intefer BATCH_SIZE = 100;
       public xxxxBatchSchedule() {
 
       }
       public void execute(SchedulableContext sc) {
              xxxxBatch bt = new xxxxBatch();
              Database.executeBatch(bt,BATCH_SIZE);
       }
}

 Schedulableクラスのinprementsではexecuteメソッドを実装する必要があります。このexecuteメソッドはglobalまたはpublicで宣言する必要があります。
 executeメソッドの中でインスタンス化されているのは前節で定義したバッチクラスです。

2.Apexスケジューラの設定

 作成したスケジューラを起動するために、Apexスケジューラを設定します。

(1)Apexをスケジュール

 1.ホームタブをクリックし、検索窓からApexを検索します。
2.検索結果のカスタムコードのApexクラスをクリックします。
 3.「Apexをスケジュール」をクリックする

Apexをスケジュールを選択
図1 Apexをスケジュールを選択

(2)スケジュールを設定

スケジュール設定
図2 スケジュール設定

 1.ジョブ名:スケジュールジョブ名を設定
 2.Apexクラス:上記で作成したスケジュールクラス(xxxxBatchSchedule)を指定
 3.頻度、開始日時、終了日時、希望開始時刻を設定する

 注意事項
 1.頻度は、「毎週」または「毎月」しか選択できません。終了日までは指定した頻度でスケジュールが実行されます。上記のスケジュールクラスで設定した時刻とは異なるタイミングでバッチが起動される場合があります。そのため、スケジュールが重複設定されないように、頻度、終了日の設定を行う必要があります。
 2.ジョブキューの状況によっては、指定した日時時刻でのジョブ起動がされない場合があります。

3.スケジュール済のジョブの確認

 バッチクラス(xxxxBatch)で設定したスケジュールは、「設定」→「スケジュール済みジョブ」で確認することができます。

スケジュール済みジョブを確認する方法
図3. スケジュール済みジョブの確認

 アクションに「Manage」と表示されている場合、これをクリックすると起点となったスケジュールの詳細を見ることができます。

スケジュールの詳細表示
図4. スケジュールの詳細表示

 スケジュールを停止する場合には最新のスケジュールの削除アクションをクリックしてスケジュールを削除する必要があります。あわせて、起点となったスケジュールが定期的に実行されるように設定されているためこれも削除する必要があります。

 SFDCのスケジュールに関してはApex スケジューラを参照してください。