こんにちは!

SlackをRSSリーダーとして使ってみたら捗り過ぎますね。恐ろしい子!

さて今日は、

細かすぎて伝わらないかもしれない、Salesforceの小ネタをいくつか紹介したいと思います。

Salesforceは機能も多く、なかなか全て把握できませんが、

ピンポイントで小ネタを知っているとぐっと作業効率が上がったりするんですよね~。

その1.開発者コンソールのカラーテーマの変更

開発者コンソールを立ち上げてから、 下記の手順でカラーテーマが変更できます。

 Help > Preferences > Editor Theme

console

全27種類?の豊富なバリエーションの中から選択できます。 いつもと違った雰囲気の中で開発をしたい時におすすめ。

その2.通貨、数値型項目の簡易入力

通貨型と数値型の項目は、桁数の大きな値を入力することもあると思いますが、

そんな時に便利なのが、簡易入力です。

標準のレコード編集画面であれば、数字と特定のアルファベットの組み合わせで簡易入力ができます。

console
console

kilo、million、billionの頭文字でそれぞれ簡易入力可能!

 

Classic・LEXのどちらも対応しています。

Classicの場合は保存時に、LEXの場合はフォーカスが外れた時に反映されます。

その3.スキーマビルダーから項目作成

スキーマビルダーの要素タブからカスタム項目をドラッグ&ドロップで作成すると、

画面遷移無し・1画面でカスタム項目を作成できます。

console
console

ガシガシと入力していけるのが良い。

項目の作成以外にも、項目レベルセキュリティも一括でチェックできたり。

スキーマビルダーは触ってみたら意外と便利!

以上3点、いくつ知っていましたか??

知ってたら、明日ちょっとだけSalesforceの操作が楽しくなる…かもしれないですね。

 

今日は、Lightning 基本コンポーネントのお話。

こんにちは!

Winter’17にアップデートして久しいですが、 Winter’17では、『Lightning 基本コンポーネント』がリリースされていることをご存じでしょうか。

robot

Lightning 基本コンポーネントは、Lightning Design System(以下、LDS)のスタイルも含んでいて、 以前のuiコンポーネントよりも扱いやすくなっている印象です。 今回は、追加された Lightning 基本コンポーネント を1つずつ確認していきたいと思います。 ※Winter’17時点でベータ版のものは除きました。


■ lightning:badge

robot
<lightning:badge label="99" />

 件数などを表示するためのバッジ。

 

■ lightning:button

robot
<lightning:button label="Download" iconName="utility:download" />

 ボタンです。  ラベルと併用して、LDSで提供されているユーティリティアイコンを利用可。

 

■ lightning:buttonIcon

robot
<lightning:buttonIcon iconName="utility:chat" />

 ラベルの無いボタン(アイコンのみ)の場合はこちらを利用。

 

■ lightning:buttonGroup

robot
<lightning:buttonGroup>
    <lightning:button label="Edit" />
    <lightning:button label="Save" />
</lightning:buttonGroup>

 ボタンを横並びにグループ化できます。  LEX風味が強くなるやつです。

 

■ lightning:buttonMenu

robot
<lightning:buttonMenu alternativeText="Menu">
    <lightning:menuItem label="Menu 1" value="1" />
    <lightning:menuItem label="Menu 2" value="2" />
    <lightning:menuItem label="Menu 3" value="3" />
</lightning:buttonMenu>

 ボタンからドロップダウンのリストを表示できます。

 

■ lightning:card

robot
<lightning:card>
    <aura:set attribute="title">
        <lightning:badge label="NEW!"/>
    </aura:set>
    <aura:set attribute="actions">
        <lightning:button label="Edit"/>
    </aura:set>
    <p class="slds-p-horizontal--small">
        <p>xxxxx</p>
        <p>xxxxx</p>
        <p>xxxxx</p>
    </p>
</lightning:card>

 レスポンシブルで定番の、カード形式のコンポーネントを実装できます。  スマートフォンでの検索結果はカードが綺麗ですよね。

 

■ lighting:icon

robot
<lightning:icon iconName="action:approval" size="large" alternativeText="Indicates approval"/>

 アイコン。  LDSで提供されているアクションアイコンが利用できます。

 

■ lightning:layout ■ lightning:layoutItem

<lightning:layout horizontalAlign="space">
      <lightning:layoutItem flexibility="auto" padding="around-small">
          1
      </lightning:layoutItem>
      <lightning:layoutItem flexibility="auto" padding="around-small">
          2
      </lightning:layoutItem>
      <lightning:layoutItem flexibility="auto" padding="around-small">
          3
      </lightning:layoutItem>
      <lightning:layoutItem flexibility="auto" padding="around-small">
          4
      </lightning:layoutItem>
  </lightning:layout>

 グリッドレイアウトを実現するためのコンポーネントで、  layoutが親要素となるコンテナ、layoutItemが子要素となるアイテムです。

 

■ lightning:select

robot
<lightning:select name="select1" label="Select an item">
    <option value="">choose one...</option>
    <option value="1">one</option>
    <option value="2">two</option>
</lightning:select>

 プルダウンリスト。  labelの要素は別途の用意が不要で、とても便利。

 

■ lightning:spinner

robot
<lightning:spinner variant="brand" size="large"/>

 ローディング用のスピナー。  LDSだと、コチラの3種類。頑張ってくれてる感は薄いですが、おしゃれです。

 

■ lightning:textarea

robot
<lightning:textarea name="myTextArea" value="initial value" 
    label="What are you thinking about?" maxlength="300" />

 テキストエリア。

 こちらもlabelの要素は用意不要です。 以上、だだっと12種類を確認してきました。

グリッドレイアウトに出来たり、お洒落なパーツが使えたり、 基本と言いつつも必要十分な機能が提供されていました!

より一層、Lightningコンポーネント開発が盛り上がりそうです。

こんにちは!

唐突ではありますが、知ってると便利かもしれないStringクラスのメソッドを8つをざっくりと紹介したいと思います。

1.abbreviate(maxWidth)

指定の文字数以上の場合、末尾を「…」にする関数 ◆サンプルコード


String str = 'じゅげむじゅげむごこうのすりきれ';

System.debug('abbreviate:' + str.abbreviate(11));

abbreviate

2.deleteWhitespace()

空白を全部削除する関数 ◆サンプルコード


String str = '  (  ●  ゜   ◇   ゜  ●  )  ';

System.debug('deleteWhitespace:' + str.deleteWhitespace());

deletewhitespace

3.startsWith(prefix)

先頭が引数の文字列かどうかを判定する関数 ◆サンプルコード


String str1 = '090-0000-XXXX';
String str2 = '030-0000-YYYY';

System.debug('str1.startsWith:' + str1.startsWith('090'));
System.debug('str2.startsWith:' + str2.startsWith('090'));

startswith

4.endsWith(suffix)

末尾が引数の文字列かどうかを判定する関数 ◆サンプルコード


String str1 = 'CustomObject__c';
String str2 = 'Account';

System.debug('str1.endsWith:' + str1.endsWith('__c'));
System.debug('str2.endsWith:' + str2.endsWith('__c'));

endswith

5.format(stringToFormat, formattingArguments)

第1引数の文字列に第2引数の文字配列で置換する関数 ◆サンプルコード


String errMsg = 'エラー:「{0}」は{1}文字以下で入力してください。';

System.debug('errMsg:' + String.format(errMsg, new String[]{'取引先名', '80'}));

format

6.join(iterableObj, separator)

リストを特定の文字列区切りの文字列に変換する関数 ◆サンプルコード


List<String>strList = new List();
strList.add('Phone <> null');
strList.add('CreatedDate = TODAY');
strList.add('NumberOfEmployees > 100');

System.debug('str:' + String.join(strList, ' AND '));

join

7.leftPad(length)、rightPad(length)

対象の文字列を引数の文字数分の半角スペースで埋めてくれる関数 ◆サンプルコード


String str = '123';

System.debug('str:leftPad :' + '|' + str.leftPad(8) + '|');
System.debug('str:rightPad:' + '|' + str.rightPad(8) + '|');

leftpad_rightpad ※ちょっと見づらいですが、ちゃんと空白で埋まっています。

8.substringAfter(separator)、substringBefore(separator)、substringAfterLast(separator)、substringBeforeLast(separator)

引数の文字列を基準にSubstringする関数 ◆サンプルコード


String str = 'n-sysdes.co.jp';

System.debug('str:substringAfter:' + str.substringAfter('.'));
System.debug('str:substringBefore:' + str.substringBefore('.'));
System.debug('str:substringAfterLast:' + str.substringAfterLast('.'));
System.debug('str:substringBeforeLast:' + str.substringBeforeLast('.'));

substringafter_substringbefore_substringafterlast_substringbeforelast

さいごに

ほかにも様々なメソッドがありますので、ちょっとした空き時間にでもApex開発者ガイドを読んでみるのはいかがでしょうか。

こんにちは!

ちょっと動画編集を勉強し始めまして。

色々調べてみてるんですが、動画の内容よりもツールの方が重要ですね。これは。

昔々にWindowsムービーメーカーを触ったきりだったので、最近の動画編集ソフトの自由度に感動しました。

kachinko

Winter’17で知らない間に変わってた話。

さて、今日もまたまた、Force.com Sitesのお話です。

今回は、Winter’17のリリースでの変更点について。

Winter’17以降、Force.com Sitesへのアクセスでデバッグログが表示されなくなっていたようです。

そういえばログが出ねー!って話、どこかで聞いたなぁ…つい最近出なくなってたんですね。

対象のリリースノートは下記。

デバッグ: 無関係なイベントログの削減

デバッグ環境が改善されたため、Salesforce 組織でより簡単に問題を解決できるようになりました。 一般ユーザのアクティビティにより、手に負えないほど大きなデバッグログは生成されなくなりました。

ブラウザの Cookie を設定し、ゲストユーザのデバッグログを有効化

一般ユーザは大量のイベントを生成するため、すぐにデバッグログがいっぱいになります。このため、一般ユーザのブラウザに特別な Cookie が含まれている場合に限り、ゲストユーザライセンスを使用するサイト訪問者に関してログが収集されます。

サイト公開後に大量にログが出続けるのを避けるためみたいです。 確かにそれは手に負えなさそう。

いでよデバッグログ。

じゃあもうデバッグログ見れねーのかというと、そうではないようで、 どうやら、クッキーを操作することでログを残せるようになるらしいので試してみました。

リリースノートを見つつ、試した手順は下記です。

  1. 1.Sitesにアクセスする。
  2.  

  3. 2.ブラウザでクッキーを操作する。
  4.         (※Chromeの場合)    

  5. 2-1.F12キー または Ctrl+Shift+J でデベロッパーツールを表示する。
  6.    

  7. 2-2.Consoleタブを表示する。
  8.    

  9. 2-3.下記をコピペ。Enterキーを押す。
  10.      document.cookie=”debug_logs=debug_logs;domain=.force.com”;  

  11. 3.再度、Sitesにアクセスする。

バッチリ出ましたッ。これで不測の事態が起きてもちょっぴり安心…かな?

kachinko

こんにちは! エナジードリンクを飲むと喉が渇いて、つい水を飲んでしまい… せっかく飲んだのにカラダの中で薄まっている気がする今日この頃です。

water

くだらない話はさておき… 今日は、再びForce.com SitesのSEO対策についてです。 前回は、robots.txtについて書きました。  Force.com SitesのSEO。Visualforceページでrobots.txtを作成して設定する。 同じ方面で、今回はSitesのURLについて掘り下げてみようと思います。

Sites URLについて本気出して考えてみる。

通常、SitesでVisualforceページを公開すると、下記のような形式のURLになるかと思います。

http://xxx.force.com/SampleSitesPage?category=staff&name=田中太郎

Visualforceページの名称が剥き出しになってしまったり、 複数のパラメータが含まれる複雑なURLになってしまいがち…。 Googleの公開している「検索エンジン最適化スターターガイド」によると、 SEO的には「ユーザフレンドリーなURLであること」「シンプルなURLであること」がより良いURLであると記載されています。

http://xxx.force.com/staff/田中太郎

こっちの方が分かりやすいですよね。 おそらく、複数名いるスタッフのうちの田中太郎さんのページなのだと直感的に分かります。 では、Force.com Sitesでここを改善する場合はどうすればいいのか? 答えは、「URL書き換えクラス」を開発して、カスタマイズすることになります。

URL書き換えクラスを実装してみようのコーナー。

Force.com Sites でURL書き換えクラスに設定できるApexクラスは、 UrlRewriterインターフェースを実装したクラスのみです。 開発者ガイド(英語)を参考にしながら実装してみます。 取引先オブジェクトを例にしたサンプルがあるので、動作を確認するだけであればコピペで試せる良きガイドです。 が、折角なので田中太郎さんに再登場してもらうことにします。

/**
 * URL書き換えクラスサンプル
 *
 * http://xxx.force.com/SampleSitesPage?category=staff&name=田中太郎
 * ↓
 * http://xxx.force.com/staff/田中太郎
 */
global with sharing class customRewriter implements Site.UrlRewriter {

    String CATEGORY_STAFF = '/staff/';
    String CATEGORY_STAFF_PAGEURL = '/SampleSitesPage?category=staff&name=';

    /**
     * 単一
     */
    global PageReference mapRequestUrl(PageReference myFriendlyUrl) {
        // URL取得。
        String url = myFriendlyUrl.getUrl();

        // '/staff/'で始まっていれば、スタッフ名で検索を行う。
        if(url.startsWith(CATEGORY_STAFF)){
            String name = url.substring(CATEGORY_STAFF.length(),url.length());

            // スタッフオブジェクトからスタッフ名でレコードを検索。
            Staff__c staff = [SELECT Id,StaffName__c FROM Staff__c WHERE StaffName__c =: name LIMIT 1];

            // スタッフレコードのIdを付与した書き換え前のURLでreturn
            return new PageReference(CATEGORY_STAFF_PAGEURL + staff.StaffName__c);
        }
        return null;
    }

    /**
     * 複数
     */
    global List<PageReference> generateUrlFor(List<PageReference> mySalesforceUrls){
        List<PageReference> myFriendlyUrls = new List<PageReference>();
        List<String> staffNames = new List<String>();

        // スタッフ名の取得
        for (PageReference mySalesforceUrl : mySalesforceUrls) {
            String url = mySalesforceUrl.getUrl();

            // '/staff/'で始まっていれば、スタッフ名をListに格納する。
            if(url.startsWith(CATEGORY_STAFF)){
                String name = url.substring(CATEGORY_STAFF.length(),url.length());
                staffNames.add(name);
            }
        }

        // スタッフオブジェクトからスタッフ名でレコードを検索。
        List <Staff__c> staffs = [SELECT Id,StaffName__c FROM Staff__c WHERE StaffName__c IN :staffNames];

        Integer counter = 0;
        for(PageReference mySalesforceUrl : mySalesforceUrls) {

            // URL取得
            String url = mySalesforceUrl.getUrl();

            // '/staff/'で始まっていれば、スタッフレコードのIdを付与した書き換え前のURLをadd
            if(url.startsWith(CATEGORY_STAFF)){
                myFriendlyUrls.add(new PageReference(CATEGORY_STAFF_PAGEURL + staffs.get(counter).StaffName__c));
                counter++;
            } else {
                myFriendlyUrls.add(mySalesforceUrl);
            }
        }
        return myFriendlyUrls;
    }
}

クラスの概要としては、  /staff/〇〇〇〇〇 で来たら、  /SampleSitesPage?category=staff&name=田中太郎 と変換するよ、というものです。 言葉で書くと、単純ですね。

設定して、動作を確認する!

実装が終わったら、Sitesの設定画面からポチポチと設定します。

water

ちなみに、UrlRewriterインターフェースが実装されていないクラスを設定するとエラーになりました。

water

設定できたら、 Idと名前が出るだけの単純なVisualforceページを用意したので、早速動かしてみます!

/SampleSitesPage?category=staff&name=田中太郎
water
/staff/田中太郎
water

どちらも同じ結果になり、うまく動作してくれていることが確認できました。 こう比べると、URLはシンプルな方がユーザビリティも高くてキレイ…。 画面のレイアウト等と同じく人の目に触れるところなので、気を付けていきたいですね。

こんにちは!

最近知ったんですが、ラムネ瓶の蓋に使われてるガラス玉は「A玉」って呼ぶらしいですね。 キチンと蓋をするためにガラス玉の形状の検査があって、 合格したものが「A玉」・不合格のものが「B玉」とされ、使わない「B玉」がオモチャとして出回ったそうです。(諸説あり)

robot

さて、1つ賢くなったところで、 今日は開発者なら避けては通れない開発環境のお話です。 Apex/Visualforceの開発を行う際の開発環境は何を使ってますか? いくつか主要なものはありますが、 比較的新しめ + 日本語でまとめてある所が無かったので、 今回は、 Visual Studio CodeでApex/Visualforceの開発環境を用意する方法をまとめたいと思います。 ちなみに、Visual Studio CodeはAtomと同じくElectronを採用していますね。 (参考) ・Visual Studio Code – WikipediaVisual Studio Codeで採用している「Electron」バージョン1.0リリース

・「Visual Studio Code」を選択する理由。

 ・他のIDEやエディタでの開発が、やや不便。   Eclipse → 慢性的に重たい。あと、全体的に白い。白過ぎる。(ブラックなテーマにしたい)   Sublime/Atom → エディタ + MavensMate がほぼ必須で、設定・立ち上げが面倒くさい。  ・トレンディである。   2016年、人気の「開発技術&ツール」はどれ? HoloLensやXamarinの人気が爆発、Visual Studio Code躍進   この記事によると、   2016年の「開発者が使いたい、IDE&開発者向けテキストエディターランキング」で、ほぼ1位タイ。   (というか1位はVisualStudio)      先述した Eclipse/Sublime/Atomのパーセンテージを合計しても、Visual Studio Codeには届いてない…。

・導入手順

 Visual Studio Codeと、拡張機能「ForceCode」 の導入手順は、以下の2STEP。    ①Visual Studio Codeをインストールする。(約2分)   下記からダウンロードできます。インストール手順は割愛。   https://code.visualstudio.com/  ②拡張機能「ForceCode」をインストールする。(約3分)   Vsual Studio Codeを立ち上げて、拡張機能サイドバーから、「ForceCode」を検索します。   ※赤枠が拡張機能のアイコンです。

robot

  インストールして、有効にします。  以上で導入は完了。早速使ってみます!

・実際に使ってみる。

 早速、Visual Studio CodeでApexコードを編集してみます。  あ、ついでに、拡張機能で「Apex」「Visualforce」(名前まんまですね)というものも入れておくと、  シンタックスハイライトが効くので見やすいです。

robot

 まずは、フォルダを適当に作って開いておきます。

robot

 次に、Ctrl + Shift + P もしくは F1キー でコマンドパレットを表示します。  ForceCodeが有効になっていれば、ここで用意されたコマンドが実行できます。  「Force」 と入力すると使用可能なコマンドが表示されるので、  今回は、編集するApexクラスを取得するために  「Force: Get Class, Page, or Trigger」のコマンドを実行します。

robot

 ログイン情報の入力を求められるので、IDとパスワードを入力+環境を選択します。

robot

 エディタでの保存時にそのままデプロイを行うかどうかの設定をします。

robot

 Visualforce、ApexClass、静的リソース、Lightningコンポーネント…が一覧で表示されます。  今回は、ApexClassを1つ選択してみます。

robot
robot

無事、開けました! 今回は、Salesforce関連の拡張機能しか入れませんでしたが、 開発者向けの拡張機能をいくつか入れることで十分開発に使えそうです。 ★開発する必要なく検索画面を作れる、検索クリエイターPRO 今なら30日無料トライアル受付中!★

こんにちは!
情報システム部インフラ担当のアンドウです。

前回は、「Windows2012でファイルサーバーを構築しよう(概要編)」で当社でのファイルサーバー構築概要をお伝えしました。

今回は、設計編をお話しします。

◆導入サーバー

導入するサーバーは、DELLの1Sラックサーバのスタンダードモデルを使用します。

【サーバー】DELL PowerEdge R320

%e7%84%a1%e9%a1%8c00008

ラックモデルなので19インチラックが必要です。

今回はDELLのNetshelter(APCのOEM)シリーズを使用します。

コンソール・UPS・HUBもラック内に収容します。

【19インチラック】DELL Netshelter SX 24U ラックエンクロージャ

%e7%84%a1%e9%a1%8c00009

【コンソール】ATEN USB DVI LCDコンソールドロワー(USBデバイス対応)CL6700

%e7%84%a1%e9%a1%8c00006

【KVMスイッチ】ATEN 1ローカル/リモート アクセス共有 8ポート PS/2-USB IP-KVMスイッチ CS1708i

%e7%84%a1%e9%a1%8c00005

瞬断・停電対策のUPSもラック内に収容します(サーバの台数分必要)。

【UPS】APC Smart-UPS 1200 RM 1U LCD 100V

%e7%84%a1%e9%a1%8c00007

ネットワークは、作環境の限界温度が50℃まで動作を可能にしたレイヤー2スイッチを使用します。

【HUB】ギガビット24ポート スタッカブル・スマートスイッチ 10G アップリンク x4 NETGEAR GS728TXS-100AJS

%e7%84%a1%e9%a1%8c00004

◆サーバースペック

■ドメインコントローラー 2台

【ベース】PowerEdge R320 , TPM
【シャーシ構成】シャーシ, 3.5” ホットプラグHDD最大4台
【CPU】インテル® Xeon® プロセッサー E5-2403 v2 1.80GHz, 10M キャッシュ, 6.4GT/s QPI, No Turbo, 80W
【メモリ】8GB (2R/1600MT/s/LV RDIMM /x8 Data Width)
【RAID】PERC H310 Mini 内蔵 RAID コントローラ
【OS用HDD※1】500GB 7,200RPM (SATA HDD/3.5インチ/ホットplug対応)ハードドライブ 2台
【光学ドライブ】8X DVD+/-RW コンボドライブ, SATA, 内蔵
【バックアップ用ディスク】外部接続のハードドライブ2TB 7,200RPM (SATA HDD/3.5インチ)ハードドライブ 1台
※1:RAID1構成で使用するので、利用できるのは500GBです。

■ファイルサーバー 2台

【ベース】PowerEdge R320 , TPM
【シャーシ構成】シャーシ, 3.5” ホットプラグHDD最大4台
【CPU】インテル® Xeon® プロセッサー E5-2403 v2 1.80GHz, 10M キャッシュ, 6.4GT/s QPI, No Turbo, 80W
【メモリ】8GB (2R/1600MT/s/LV RDIMM /x8 Data Width)
【RAID】PERC H710 Mini 内蔵 RAID コントローラ、 512MB NV キャッシュ
【OS用HDD※2】300GB 15,000RPM (6Gbps SAS HDD/3.5インチ/ホットplug対応)ハードドライブ 2台
【データ用HDD】3TB 7,200RPM N-Line (6Gbps SAS HDD/3.5インチ/ホットplug対応)ハードドライブ 2台
【光学ドライブ】8X DVD+/-RW コンボドライブ, SATA, 内蔵
※2:RAID1構成で使用するので、利用できるのはOS用500GB,データ用3TBです。

■バックアップ サーバー 1台

【ベース】PowerEdge R320 , TPM
【シャーシ構成】シャーシ, 3.5” ホットプラグHDD最大4台
【CPU】インテル® Xeon® プロセッサー E5-2403 v2 1.80GHz, 10M キャッシュ, 6.4GT/s QPI, No Turbo, 80W
【メモリ】8GB (2R/1600MT/s/LV RDIMM /x8 Data Width)
【RAID】PERC H310 Mini 内蔵 RAID コントローラ
【OS用HDD※3】500GB 7,200RPM (SATA HDD/3.5インチ/ホットplug対応)ハードドライブ 2台
【光学ドライブ】8X DVD+/-RW コンボドライブ, SATA, 内蔵
【バックアップ用ディスク】外部接続のハードドライブ 2TB 7,200RPM (SATA HDD/3.5インチ)ハードドライブ 10台
※3:RAID1構成で使用するので、利用できるのは500GBです。

■セキュリティ サーバー 1台

【ベース】PowerEdge R320 , TPM
【シャーシ構成】シャーシ, 3.5” ホットプラグHDD最大4台
【CPU】インテル® Xeon® プロセッサー E5-2403 v2 1.80GHz, 10M キャッシュ, 6.4GT/s QPI, No Turbo, 80W
【メモリ】8GB (2R/1600MT/s/LV RDIMM /x8 Data Width)
【RAID】PERC H310 Mini 内蔵 RAID コントローラ
【OS用HDD※4】500GB 7,200RPM (SATA HDD/3.5インチ/ホットplug対応)ハードドライブ 2台
【データ用HDD】2TB 7,200RPM (SATA HDD/3.5インチ/ホットplug対応)ハードドライブ 2台
【光学ドライブ】8X DVD+/-RW コンボドライブ, SATA, 内蔵
※4:RAID1構成で使用するので、利用できるのはOS用500GB,データ用2TBです。

◆ソフトウェアスペック

殆ど定番のソフトウエアばかりです。

【OS】Windows Server 2012 R2
【UPS管理用】PowerChute Business Edition
【バックアップ】Symantec Backup Exec
【ウイルス対策】Symantec Endpoint Protection
【アクセスログ収集】AMIYA ALog ConVerter

◆Active Directoryの設計

【構成は可能な限りシンプルに】
Active Directory設計において、まず、可能な限りシンプルな構成にするということです。ドメイン構成を複雑にすると、トラブルの元になり得るとともにトラブルシューティングも困難になりかねません。まずは、シングルドメイン構成で要件が満たせるかを検討します。

【基本構成設計は慎重に】
将来の拡張性も考慮して、構築後にドメイン構成を変更することがないよう設計時に十分な検討が必要になります。例えば、既存ドメインの上位へドメインを追加することができません。

【既存環境の考慮を忘れずに】
Active Directory導入時は既存環境を考慮した設計が必要になります。既存環境にDNSサーバがある場合、Windows Server 2012 R2標準搭載のDNSサーバとの連携を考える必要があります。

■構築後の変更が困難な項目

【DNSサーバ】
Active Directoryサーバーに DNS サーバをインストールして構成し、優先 DNS サーバーとして使用するようにします。既存DNSサーバを用いてActive Directory構築することも出来ますが、メリットも特に無いためお勧めしません。既存のDNSサーバを用いる場合、Active DirectoryのDNSとしてはwindows DNSサーバを使用し、既存のDNSサーバと連携するようにします。

【DNSゾーン】
Active Directoryを構築するためには、標準プライマリゾーン、もしくはActive Directory統合ゾーンの作成が必須となります。DNSサーバはActive Directory統合ゾーンを用いることにより、以下のメリットを得ることが出来ます。

・ゾーンのマルチマスタ更新
・レプリケーションの暗号化
・DNSの動的更新
・リソースレコード登録のアクセス制御

【NetBIOSの名前解決方法】
NetBIOSの名前解決には、WINSによる名前解決を行うようにすることにします。WINSはNetBIOS名とIPアドレスのマップを動的に更新するデータベースです。動的に更新するため、DHCPでIPアドレスを割当てられたクライアントに対する名前解決も容易に行えます。

【ドメイン構成】
人事異動や組織変更の際の管理を考慮して可能な限りシングルドメイン構成にします。部署単位でユーザー管理したいという場合は、ドメイン内でOUを作成することで対応できます。ドメイン名は運用開始後には変更しないように、慎重に決定してください。Active Directoryの再構築をせずにドメイン名の変更が可能ですが、変更手順がとても複雑なため、現実的ではありません。特にマルチドメイン構成の最上位のドメイン名は影響が大きいため、Active Directory構築後にドメイン名を変更することがないようにします。別々に構築したフォレストは、後から統合することはできません。フォレスト間で信頼関係を結ぶと、フォレスト間で相互にリソースアクセスができるようになります。但し、その場合でもGC、スキーマ、サイトの統合はできません。
Active Directory設計で言えることは、できるだけシンプルな構成にするということです。

今回は、以下の構成にします。

 【機能レベル】フォレスト Windows Server 2012 R2
 【ドメイン】Windows Server 2012 R2
 【AD構成】フォレスト シングルフォレスト
 【ドメイン】シングルドメイン
 【サイト】シングルサイト
 【DNS】ドメイン名 n-sysdes.co.jp
 【ゾーンの種類】Active Directory 統合ゾーン

■要件にあわせた設計項目

【OU(組織単位)】
Active Directoryで管理するオブジェクトが決定したら、オブジェクトを格納するOUの構成を決定します。OU構成の設計は管理の委任やグループポリシーの適用を視野に入れて行います。OUは階層化が可能でが、性能劣化を考慮して階層は深くても5階層までにするようにします。OUは管理(管理の委任、グループポリシーの適用可否など)を目的として作成しますが、アクセス権を与えるためのものでありません。

【サイト】
サイトは、ディレクトリ複製のためのトラフィック制御や、ログオン認証を受けるDCを明示的に指定することを目的とします。Active Directoryドメイン内ではDC間の情報同期のため定期的にディレクトリ情報の複製を行います。サイト間では複製トラフィックのスケジュールが細かく定義でき、例えば毎日深夜の時間帯のみ複製を行うといった制御が可能です。各拠点にDCを配置することによって、コンピュータは同一サイトにあるDCにログオン要求を行うため効率的なログオン認証処理が実現できます。

【GCの配置】
GCの配置はクライアントのログオンやディレクトリの検索など、クライアントの要求に対する応答性能に大きくかかわります。GCはフォレスト内で最初にセットアップしたDC上に自動的に作成されますが、手動による構成で、任意のDCにGCの役割を持たせることが可能です。同じサイトにGCがない場合、他サイトのGCに参照に行くてめ、ネットワーク帯域幅によってはパフォーマンスに影響を与えることがあります。

【グループポリシーとローカルグループポリシー】
Windowsには、OSやユーザーの設定を統一する機能としてグループポリシーが提供されています。グループポリシーは、Active Directory環境で利用するグループポリシーと個々のコンピュータで利用するローカルグループポリシーから構成されています。また、上位OUに適用したグループポリシーは下位OUにも適用されるため、下位OUほど多数のグループポリシーが適用されることになります。

◆ファイルサーバーの設計

多くの企業では、複数のファイルサーバーを運用していると思います。ファイルサーバーのディスク容量が不足した際にはハードディスクを追加するのではなく、ファイルサーバーそのものを増設する場合もあります。しかし、ファイルサーバーを増設するると、ユーザーは目的のファイルやフォルダーにアクセスするのに新しいファイルサーバーの名前覚える必要があります。

【分散ファイルシステムの使用】
「DFS名前空間」と呼ばれる機能によって、複数のファイルサーバーにある共有フォルダーの一元管理をします。DFSでは「名前空間サーバー」という“代表となる特殊なファイルサーバー”上にフォルダーを作成し、その下に複数のファイルサーバーに散在している共有フォルダー(「フォルダーターゲット」と呼ぶ)をリンクさせることで他のファイルサーバーの存在(ファイル共有のアドレス)を隠す仕組みになっています。実は、このDFSと同じような仕組みは、従来のファイルサーバーでも実現できます。一つのファイルサーバーを決め、そこに各ファイルサーバーの共有フォルダーの「ショートカット」を置けば実現できます。では、DFSを利用するメリットとは何か、DFSは企業利用で求められる可用性を含め、ファイルサーバーをより効率良く活用するための機能を提供してくれます。実際の可用性の構成は、名前空間の種類によってアプローチが異なますが、「ドメインベースの名前空間」の場合は複数の名前空間サーバーで可用性を確保します。

今回は、以下の構成にします。

【名前空間サーバー】ドメインコントローラー
【名前空間】ドメインベースの名前空間
【可用性の確保】DFSレプリケーション
【レプリケーション】フルメッシュ トポロジー

◆バックアップサーバーの設計計

バックアップソフトは、Symantec Backup Execを使用します。インストールは、OSドライブに行います。バックアップメディアは、外部接続のハードドライブ10台を使用し、ライブラリ管理はBackup Execに任せます。

【バックアップのスケジュール】

・日曜の夜間にフルバックアップを行います。
・月曜日~土曜日の夜間に増分バックアップを行います。

※システムのバックアップは、Windowsのバックアップ機能の使用して各サーバーの外部接続のハードドライブに毎日取得します。復元には、ベアメタル回復を使用します。

◆セキュリティサーバーの設計

OS更新・パッチの適用は、Windows Server Update Servicesを使用します。インストールは、OSドライブに行います。

ウイルス対策ソフトは、Symantec Endpoint Protectionを使用します。アクセスログ収集ソフトは、AMIYA ALog ConVerterを使用します。インストールは、データドライブに行います。収集したアクセスログは、定期的にファイルサーバーにもコピーして管理します。

次回は、「ファイルサーバを構築しよう(実装編)」をお話しします。

システム運用・管理サポートサービス

 弊社では、お客様の抱えているシステムの問題について全て当社が対応いたします。また、今後、システムの導入を検討もしくは、入れ替えを検討されているお客様につきましては、最適なハードウェア・ソフトウェア・ネットワーク等を当社からご提案いたします。
詳しくはこちらをご参照ください。

こんにちは!

AWS EC2で個人用のRedmineを立ち上げてみました。 Redmineって落ち着きますよねぇ〜…職業病でしょうか?

難しい顔で考え込むプログラマ

開発中、SOQLを書いている時に子リレーション名が知りたくなった時。 Salesforceにログインして、カスタムオブジェクトの設定画面を開いて… とか 標準オブジェクトの名前からググって… とか たまのことですが、面倒なので、 いつでもコピペで確認できるようにApexからの参照方法を確認してみました。

・オブジェクトのメタデータから子リレーション名の一覧を取得してみる。

Schema.ChildRelationshipが便利です! オブジェクトのメタデータからリレーションを特定し、リレーション名を取得できます。 例として、取引先オブジェクトだと下記のような形で取得することができます。

Schema.DescribeSObjectResult result = Account.SObjectType.getDescribe();
List<Schema.ChildRelationship> childRelation = result.getChildRelationships();

for (Schema.ChildRelationship c : childRelation) {
    System.debug(c.getChildSObject().getName() + ' / ' + c.getRelationshipName());
}
開発者コンソール1

・オブジェクトを指定して、リレーション名を取得する。

さて、先述したのは取引先(と諸々の子オブジェクト達)の取得でしたが、 それだとコピペで使えないので、分かりやすく文字列で指定できるようにしときます。

String parentObject = 'Account';
String childObject = 'Contact';

for (Schema.ChildRelationship c : Schema.getGlobalDescribe().get(parentObject).getDescribe().getChildRelationships()) {
    if (c.getChildSObject()==Schema.getGlobalDescribe().get(childObject)) {
        System.debug('リレーション名:'+c.getRelationshipName());
    }
}
開発者コンソール2

これで、 オブジェクトのAPI参照名を親子で指定すると、リレーション名が分かるようになりました。 これで完璧・・・?

・いや、コピペ出来ない時もある。事前に対策!

プログラマーは忙しいのです…コピペすらできない時のために、 ざっくりと標準オブジェクトのリレーション名を事前にまとめておきます。 AccessibleとかQueryableでフィルタリング済み。重複は、気にしない。

親オブジェクト 子オブジェクト 子リレーション名
契約 行動 Events
メモ Notes
注文 Orders
ToDo Tasks
注文 添付ファイル Attachments
行動 Events
メモ Notes
注文 Orders
ToDo Tasks
メールテンプレート 添付ファイル Attachments
キャンペーン 添付ファイル Attachments
キャンペーン ChildCampaigns
行動 Events
商談 Opportunities
ToDo Tasks
取引先 取引先 ChildAccounts
納入商品 Assets
添付ファイル Attachments
ケース Cases
取引先責任者 Contacts
契約 Contracts
行動 Events
メモ Notes
商談 Opportunities
注文 Orders
ToDo Tasks
取引先責任者 納入商品 Assets
添付ファイル Attachments
ケース Cases
契約 ContractsSigned
行動 Events
メモ Notes
ToDo Tasks
リード 添付ファイル Attachments
行動 Events
メモ Notes
ToDo Tasks
商談 添付ファイル Attachments
行動 Events
メモ Notes
ToDo Tasks
商品 納入商品 Assets
添付ファイル Attachments
行動 Events
メモ Notes
ToDo Tasks
納入商品 納入商品 ChildAssets
添付ファイル Attachments
ケース Cases
行動 Events
メモ Notes
ToDo Tasks
ケース 添付ファイル Attachments
ケース Cases

 

こんにちは!
情報システム部インフラ担当のアンドウです。

現在、クラウドが主流になりつつありますが、まだまだ、オンプレでサーバー運用してる企業も多いと思います。

そこで、昨年、老朽化により故障の頻度が高まっていた当社のサーバーを、クラウドへの移行も検討しましたが、性能・パフォーマンス・コスト面等を比較した結果、オンプレでの再構築を行った構築手順について説明したいと思います。

◆ファイルサーバーとは

企業内LANの最も基本的な機能の一つで、LANやWANなどのネットワーク上でファイルを共有するために設置されるサーバのことです。

自身の管理している記憶装置をネットワーク上の他のコンピュータと共有し、外部から利用できるようにするコンピュータのことです。

複数のクライアントが同じファイルを必要とする場合、ファイルを共有しておけばその転送の手間が省けます、また、ファイルを更新した際に起こりがちな不整合を防ぐことができます。

ファイルサーバ上にあるファイルは(許可されていれば)誰でも他のコンピュータから読みこんだり書きこんだりできるため、データの一括管理が可能になります。

ファイルサーバにとって最重視される使命は、その中に保存されているファイルがきちんと読み書きできることです。

ハードディスクは元来壊れやすい部品であり、ファイルサーバにとってハードディスクの故障は最大の敵といえます。

バックアップなどのデータ管理も一括して行えますが、複数のクライアントにリスクが分散していた所を、一括して集中した分だけデータ紛失のリスクは上がります。

すなわちリスクが集中するため(要するに、ファイルサーバ1台または数台に障害が発生しただけでシステム全体の障害となる)、ファイルサーバの信頼性は重要といえます。

◆新システム構築条件

・機器の設置場所
 システム設置場所は、自社内サーバ室内とする(オンプレミス)

・今回調達する機器は、19インチラックマウントタイプとする。
 ラックマウントサイズは、省スペース化を考慮し24U 以内の製品を導入する。
 UPS 装置、CPU 切替機、コンソールユニット(キーボード,モニタ等) を含む。

・各機器については、必要以外のサービスを停止する。

・最新のセキュリティパッチの適用などのセキュリティ対策を施すこと。

◆基本仕様

a.利用ユーザー数:100人(ストレスなく読込・書込・更新・削除等が可能なシステムとする)
b.同時アクセスユーザー数に制限がないこと。
c.作成される共有フォルダ数に事実上の登録数制限がないこと。
d.ファイルやフォルダ単位でアクセス権の設定が可能であること。
 アクティブディレクトリを利用したユーザー認証設定および権限設定が可能なこと。

infra_access_right

◆機器仕様
a.筐体は正副の2重化構成とし,副サーバは別物理筐体にて構成されること。

infra_equipment_configuration

b.正・副サーバ間でレプリケーションしていること。
 運用をスムーズに実施するために、同ソフトは機器同梱のソフトで実現すること。
 搭載OS に対して動作検証が保証されているソフトで実現すること。
c.データ領域実効容量 2TB 以上
e.データ領域はRAID1のホットスワップ対応HDD(SAS、またはNL-SAS)
f.ディスク容量の拡張が容易に行えること
h.機器で使用する総アンペア数は省電力を考慮し最大15A以内とすること
i.バックアップを3世代以上保存可能なこと
j.導入システムに対しウィルス対策を行うこと。
k.リモートアクセスにより、システムの管理が可能なこと

※バックアップデータは別筐体に保存すること
※バックアップ取得については業務時間中のパフォーマンスに影響を与えない方法で行うこと

今回は割と規模の小さなシステムですが、機能的には本格的なものを構築します。

ファイルサーバーの構築を目的としますが、認証機能としてアクティブディレクトリとバックアップ機能としてSymantec Backup Execのサーバも併せて構築します。

次回は、「ファイルサーバを構築しよう(設計編)」をお話しします。

システム運用・管理サポートサービス

 弊社では、お客様の抱えているシステムの問題について全て当社が対応いたします。また、今後、システムの導入を検討もしくは、入れ替えを検討されているお客様につきましては、最適なハードウェア・ソフトウェア・ネットワーク等を当社からご提案いたします。
詳しくはこちらをご参照ください。

この技術ブログの読者の方の中にはSalesforce初心者という方もいらっしゃるのではないかと思います

Salesforce、まだまだわからないことだらけですが…これから私と一緒に理解を深めていきませんか!? という前置きからの 今回は、来る9/30(金) 19:30~20:30に弊社6F会議室にて催された TIS様とのSalesforceの技術情報の合同勉強会の簡単なレポートをいたします!

TIS様との合同勉強会について

TIS・弊社間での技術情報交換を目的に催される勉強会も今回は2回目~ テーマはフリー、LT(5分)+質疑応答(5分)を7名のスピーカーが 熱いトークを繰り広げました!!

それでは短いですが、レポご覧くださいませ!! ——–

 

初心者目線のSalesforce~便利機能~

Salesforce歴4ヶ月ということで、ドがつく初心者の私でもイメージしやすい切り口のLTでした。

初心者向けの便利機能…どれだけあるのかな?と思ったらこんなにたくさん!!(*.*)

でも、Salesforceの勉強をどこから始めるか迷っている時の指針になりますね img_1650

Summer’16選択リストについて

Salesforce Summer’16からグローバル選択リストがすべての組織で使用できるようになったということで グローバル選択リストを使用することのメリット・デメリット合わせての解説がわかりやすい!

質疑ではレコードタイプがどうかかわってくるか?が焦点になるとのこと…(ムムム…勉強します… img_1654

最強のデータストレージ拡張

Developer Editionでは容量が足りないんだよ~!という話は、私の周りのSalesforce案件参画者の間でも フムフムと聞く話ではあったのですが、こんなに少ないなんてというのが驚きでした。

理想と現実の折り合いをつける…なんとも耳の痛い話です。 img_1656

Salesforceは使いやすいのか使いづらいのか

非Salesforceシステム開発からの移行組ということで、共感できる内容が 多く含まれたものでした。

お客様目線でカスタマイズを提案することの大切さを改めて感じました。

カスタマイズについても勉強していかなくては! img_1658

Pepperのリモコンアプリを作ってみた

弊社内新規事業企画室でPepperアプリの開発に携わっている末吉さん、現在のPepperが果たす役割に ついてのLTでした。

街でPepperを見かけることが少しづつ増えてきていますが、今後はどうなっていくの でしょう?

現在では諸事情につき公開が幻に終わっているアプリ、リベンジしたいですね~… img_1660

開発補助ツールTesforceについて

Force.comデベロッパー向けのChrome拡張機能、Tesforce紹介のLTでした。

システム開発全般でもテストデータづくり、テストコード作りは頭を悩ませる問題ですよね。

この部分については、Salesforceに限らずなかなかピリっとしたものが出てこない難しいものを感じます(>_<) img_1663

(テーマは伏せさせていただきます)

テーマと内容はお口チャックということで、ここは私の所感だけ。。 「お客様のビジネス価値の向上に貢献できていますか?」という問いかけがとても胸にずしーんときました!

目先のシステム作りだけではなく、お客様のことを知り、何を望んでいるのか?しっかり把握していくする必要が ありますよね。

こちらもまたSalesforceに限らずシステム開発すべてにおける課題です…! img_1665_2 ——– いかがでしたでしょうか? えっ?もっと見たい!?いやいや今回はここまで… 当社では、今後も勉強会・発表会が活発に行われる予定ですので 引き続きレポートしていきたいと思います!!

こんにちは!

今回は、みんな大好きな開発者コンソールの便利機能についての紹介です! 開発したApexコードやVisualforceページのパフォーマンスを確認する際に、 皆さんはどのような方法で確認しているでしょうか。 ―――どこのメソッドで処理に時間がかかっているのか? ―――ガバナ制限に近い数値になっていないか? そんな作業時の疑問を解決できるのが、 開発者コンソールの「Execution Overview」です。 早速、確認してみましょう! 開発者コンソールに不慣れな方は↓を見てからどうぞー。 開発者コンソールの機能 | Salesforce

「Execution Overview」を表示させてみる!

Execution Overview」は、開発者コンソールから確認できるログの一部です。 まずは、何かしら適当なログを出力させるため、匿名実行からSOQLとSystem.debugを実行します。 Open Logにチェックを入れて、実行後にログのタブが自動で開くようにしておきます。

console1

実行後、ログのタブが開いたら、 Debugから、View Log Panels…をクリックします。

console2

すると、Select Panelsウィンドウが開くので、 「Execution Overview」にチェックを入れて、ウィンドウを閉じます。

console3

これでログタブから、「Execution Overview」 が確認できるようになりました!!

console4

実行した処理の結果を確認してみる。

では、「Execution Overview」のTimelineタブを見てみましょう。 Timelineタブでは、 実行された処理と、その処理時間を視覚的に確認することができ、 バーをクリックすることで、コンソール上部にその詳細を表示できます!

console6

また、バーの左側には、具体的な数値も表示されています。 今回のSOQLは、ごくごくシンプルなものなので、8.78ミリ秒しかかかっていないことが分かります。 全体から見ると、44.74%で… for文でSystem.debugを出してる所の方が、10.85ミリ秒かかっていて… といったようなことも一目瞭然になりますね! Timelineタブ以外にも、 SaveOrderタブではDMLイベントのあったオブジェクトとそのイベントの発生元が確認できたり、 まだまだ便利な機能がありそうなので、機会があればもっと使ってみたいですねー。

こんにちは!

開発者コンソールの匿名実行Apexツールは活用してますか? そもそも、開発者コンソールの匿名実行Apexツールとはなんだ!?って方、 下記ヘルプを参照してください。m(_ _)m https://help.salesforce.com/apex/HTViewHelpDoc?id=code_dev_console_execute_anonymous.htm&language=ja 本題ですが、 このツールを使っていろいろとやってみようと思います。 その第1弾として、クラスとトリガのテストカバー率を取得するApexコードを書いてみました! ※テストクラスの実行はしません。現在のカバー率を取得します。 まず、なぜこのコードを書いたかというと、ご存知の方もいらっしゃると思いますが、 Winter’14のリリースでApexクラス一覧からクラスのカバー率の列が削除されましたよね。

リリースノート抜粋_コードカバー率について

https://resources.docs.salesforce.com/186/latest/ja-jp/sfdc/pdf/salesforce_winter14_release_notes.pdf ↑306ページ なんで削除されたんだ?と思った方も多いのではないでしょうか。(たぶん…) ということで、どうにか一覧表として取得できないかなぁと思い、書いてみました。 開発者コンソールの[Debug]->[Open Execute Anonymous Window]で匿名実行Apexツールを開き、 下記コードを貼り付けて[Execute]ボタンをクリックすると、 ドキュメントの「私の個人ドキュメント」フォルダにクラスとトリガのカバー率一覧のファイルが XMLスプレッドシート形式で保存されます!!


// ClassとTriggerのカバー率を取得するクエリ
String queryStr = 'Select+id,ApexClassorTriggerId,ApexClassorTrigger.Name,NumLinesCovered,NumLinesUncovered+from+ApexCodeCoverageAggregate+order+by+ApexClassorTrigger.Name';

HttpRequest req = new HttpRequest();
req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+'/services/data/v37.0/tooling/query/?q='+queryStr);
req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
req.setHeader('Content-Type', 'application/json');
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);

Map<String, Object> objMap = (Map<String, Object>)JSON.deserializeUntyped(res.getBody());

List<Object> objList = (List<Object>)objMap.get('records');

// クラス一覧ワークシート
String clsListWS = '';
// トリガ一覧ワークシート
String trgListWS = '';

clsListWS += '<Worksheet ss_Name="クラス一覧">rn' +
               '<Table ss_ExpandedColumnCount="7" x_FullColumns="1" x_FullRows="1" ss_DefaultColumnWidth="54" ss_DefaultRowHeight="13.5">rn' +
                 '<Column ss_AutoFitWidth="0" ss_Width="21.75"/>rn' +
                   '<Row>rn' +
                     '<Cell><Data ss_Type="String">クラス一覧</Data></Cell>rn' +
                   '</Row>rn' +
                   '<Row>rn' +
                     '<Cell><Data ss_Type="String">No</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">Id</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">Name</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">NumLinesCovered</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">NumLinesUncovered</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">TotalNumLines</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">Coverage</Data></Cell>rn' +
                   '</Row>rn';


trgListWS += '<Worksheet ss_Name="トリガ一覧">rn' +
               '<Table ss_ExpandedColumnCount="7" x_FullColumns="1" x_FullRows="1" ss_DefaultColumnWidth="54" ss_DefaultRowHeight="13.5">rn' +
                 '<Column ss_AutoFitWidth="0" ss_Width="21.75"/>rn' +
                   '<Row>rn' +
                     '<Cell><Data ss_Type="String">トリガ一覧</Data></Cell>rn' +
                   '</Row>rn' +
                   '<Row>rn' +
                     '<Cell><Data ss_Type="String">No</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">Id</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">Name</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">NumLinesCovered</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">NumLinesUncovered</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">TotalNumLines</Data></Cell>rn' +
                     '<Cell><Data ss_Type="String">Coverage</Data></Cell>rn' +
                   '</Row>rn';

Integer clsCnt = 1;
Integer trgCnt = 1;
for(Object obj : objList){
    Map<String, Object> codeCoverageObj = (Map<String, Object>)obj;
    Map<String, Object> clsOrTrgObj = (Map<String, Object>)codeCoverageObj.get('ApexClassOrTrigger');
    
    Double numLinesCovered = Double.valueOf(codeCoverageObj.get('NumLinesCovered'));
    Double totalNumLines = Double.valueOf(codeCoverageObj.get('NumLinesCovered')) + Double.valueOf(codeCoverageObj.get('NumLinesUncovered'));
    
    // クラス単体のカバー率を計算
    Decimal coverage = 0;
    if(numLinesCovered != 0){
        coverage = (numLinesCovered / totalNumLines) * 100;
        coverage = coverage.setScale(0, System.RoundingMode.HALF_UP);
    }
    
    String clsOrTrgId = String.valueOf(codeCoverageObj.get('ApexClassOrTriggerId'));
    
    // ClassのIdのPrefix
    if(clsOrTrgId.startsWith('01p')){
        clsListWS += '<Row>rn' +
                       '<Cell><Data ss_Type="Number">' + clsCnt + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="String">' + clsOrTrgId + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="String">' + String.valueOf(clsOrTrgObj.get('Name')) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="Number">' + String.valueOf(numLinesCovered) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="Number">' + String.valueOf(codeCoverageObj.get('NumLinesUncovered')) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="Number">' + String.valueOf(totalNumLines) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="String">' + coverage + '%' + '</Data></Cell>rn' +
                     '</Row>rn';
        
        clsCnt++;
    }
    // TriggerのIdのPrefix
    else if(clsOrTrgId.startsWith('01q')){
        trgListWS += '<Row>rn' +
                       '<Cell><Data ss_Type="Number">' + trgCnt + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="String">' + clsOrTrgId + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="String">' + String.valueOf(clsOrTrgObj.get('Name')) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="Number">' + String.valueOf(numLinesCovered) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="Number">' + String.valueOf(codeCoverageObj.get('NumLinesUncovered')) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="Number">' + String.valueOf(totalNumLines) + '</Data></Cell>rn' +
                       '<Cell><Data ss_Type="String">' + coverage + '%' + '</Data></Cell>rn' +
                     '</Row>rn';
        
        trgCnt++;
    }
}

clsListWS += '</Table>rn' +
           '</Worksheet>rn';

trgListWS += '</Table>rn' +
           '</Worksheet>rn';

String workBook = '<?xml version="1.0"?>rn' +
                  '<?mso-application progid="Excel.Sheet"?>rn' +
                  '<Workbook     >rn' +
                  clsListWS +
                  trgListWS +
                  '</Workbook>';

Document doc = new Document();
String timeStamp = DateTime.now().format('yyyyMMddHHmmss');
doc.Name = 'TestCoverage_' + timeStamp + '.xml';
doc.DeveloperName = 'TestCoverage_' + timeStamp + '_xml';
doc.FolderId = UserInfo.getUserId();
doc.Body = Blob.valueOf(workBook);
doc.type = 'xml';
insert doc;

※このコードを実行前に「リモートサイトの設定」が必要となります。 [設定]->[セキュリティのコントロール]->[リモートサイトの設定]で下記URLを設定しておいてください。 https://【ログイン環境のインスタンス】.salesforce.com 出力されるファイルはこんな感じです↓

カバー率_出力ファイル

ぜひ活用してみてください!

こんにちは!

今日は、 マスタデータ管理について紹介したいと思います! Salesforceでマスタデータ管理というと… カスタムオブジェクトや、カスタム設定、カスタムメタデータタイプ等々、いくつか思い浮かびますが、 今日は静的リソースを使った管理方法についての紹介です。 それぞれメリット・デメリットありますが、 静的リソースの特徴は、JSONファイルで管理できる点にあります。

json

あとは、 カスタムオブジェクトやカスタム項目をポチポチ作る必要がない、 データローダを使わない所も良いですね! 今回は、ありがちな「都道府県データ」を例に、早速やっていきますよ~。 (さらに…)

こんにちは!

さて今回は、変更セットでのリリース時に遭遇したエラーを紹介します。 ある日、変更セットでのリリース時、 致命的なという仰々しい連体修飾がされたエラーが発生しました。

致命的なエラー

エラーメッセージは下記。 「アクセス権がないため要求を実行できません。 データの所有者、またはシステム管理者にお問い合わせください。」 所有者…?アクセス権…? 思い当たる節が無く、以下、色々調べてみたログです。 (さらに…)

こんにちは!

Chatterの投票機能ってご存知でしょうか? 投票 | Salesforce この機能では、 Chatter上で、質問選択肢を設けて、それを見たユーザから投票を受け付けることができます。

chatter投票機能イメージ

ただし、上記のへルプにもある通り、 標準のインターフェースからは、 『誰がどの選択肢に投票したのか?』という部分については確認できないようになっています。 そこで今回は、 Apexで、投票機能に関連するオブジェクトから誰がどの選択肢に投票しているか確認してみたいと思います。 (さらに…)

contact

ご相談・ご質問等ございましたら、お気軽にお問い合わせください。

翻訳