月別アーカイブ: 2014年7月

親ページなら子ページのリストを、子ページなら記事本文を表示する その2

前回、リスト化する方法でこんなことを書いた。

が、こんなもっと良い方法があった。

「custom-xxxxx.php」というファイルを作るところまでは共通で、その中身。

wp_list_pages を使うともっとすっきりもっとわかりやすくもっと使いやすい。

// リスト化したいページのIDを指定
$allow_list_id = array('0','108','122','146');

// array_search で $allow_list_id の中に現ID(get_theid())=リストを表示したいページが含まれているかどうか判別
if(array_search(get_the_id(),$allow_list_id)){
 
 // パラメータ chiled_of を指定することで、そのページのサブページを表示させる
 $child_of = get_the_id();
 
 $list_paras = array(
     'post_type'   => 'カスタム投稿タイプ名',
     'show_date'   => '',
     'exclude'     => '',
     'depth'       => '0',
     'date_format' => get_option('date_format'),
     'child_of'    => $child_of,
     'title_li'    => '',
     'echo'        => 1,
     'sort_column' => 'post_modified',
     'link_before' => '',
     'link_after'  => '',
     'exclude_tree'=> '' );

 // てことで表示
 wp_list_pages($list_paras);

パラメータは環境によってお好きなように。。。

前回の方法より、今回の方が使いやすいかな。

親ページなら子ページのリストを、子ページなら記事本文を表示する

カスタム投稿タイプでいくつかのページを作ったけど、親ページには子ページのリストを表示したい!
ということで、下記の方法に辿り着いたわけだけど、なんか、もっと簡単な方法ないのかな。。。?

とりあえずはできてるのでメモ

テンプレートヒエラルキー抜粋

上図をみるとカスタム投稿は single-$posttype.php を見に行く。
そして、ブログ投稿は single-post.php を見る。

そこで、まず、single-post.php があるかどうか確認。
標準で存在するものと思っていたファイルだけれど、なかったので single.php を single-post.php としてコピー。

また、single.php は最終的に他のテンプレートからも参照される可能性があるので、カスタム投稿ファイル用に single-$posttype.php なるものを作るほうがベターかも。
これは、「親ページでは子ページのリストを表示したいカスタム投稿タイプ」のページ分、作る必要がありそう。

とはいえ、上図で single.php を参照するもう一つは「添付ファイル投稿」なので、直接 single.php を書き換えてしまっても良いのかな。
(実は、今のところ、直接 single.php を書き換えてたりする)

さて、これで「ブログ投稿」は「single-post.php」を参照、「カスタム投稿タイプ」は「sinle.php」を参照することになる。

ということは、single.php に手を加えれば、リスト表示ができる?

確かに、single.php にリスト化するスクリプトを記述すれば表示はされる。
けど、よく見るとコンテンツを表示するために「get_template_part()」が使われている。

「ブログ投稿」の場合には「get_template_part( 'content', get_post_format() );」となっていて
content-[post_format].php というファイルが読み込まれるようになっている。

であれば、「カスタム投稿タイプ」を表示する際には「single.php」を読み込み、さらにそこから「custom-xxxxx.php」といったファイルを読み込ませれば効率的。

この場合には「get_template_part( 'content', 'xxxxx' );」といった具合に。
xxxxxは任意で、今回は「custom」としてみようかと思う。

というわけで、content.php を content-custom.php とでもしてコピーし、下記内容に適宜書き換える。

 <?php if ( is_search() ) : // Only display Excerpts for Search ?>
  <div class=”entry-summary”>
   <?php the_excerpt(); ?>
  </div><!– .entry-summary –>
 <?php else : ?>
  <div class=”entry-content”>

// 親ページかどうかの判別。親ページは $post->post_parent が「0」
  <?php if ( is_single() && $post->post_parent == 0 ) : ?>
   <ul>
    <?php
    $all_lists = get_posts( array( 'post_type' => get_post_type($post),
                                   &#39orderby&#39 => 'menu_order',
                                   'order' => 'ASC',
                                   'posts_per_page' => 30));
    array_shift($all_lists);
    foreach($all_lists as $post) {
     setup_postdata($post);
    ?>
    <li>
     <a href=”<?php the_permalink() ?>”><?php the_title() ?></a>
    </li>
    <?php
    }
    ?>
   </ul>
  <?php else : // 子ページなら投稿記事本文を表示 ?>
   <?php the_content( __( 'Continue reading <span class=”meta-nav”>→</span>', 'twentytwelve' ) ); ?>
   <?php wp_link_pages( array( 'before' => '<div class=”page-links”>' . __( 'Pages:', 'twentytwelve' ), 'after' => '</div>' ) ); ?>
  <?php endif; ?>
  </div><!– .entry-content –>
 <?php endif; ?>

とまぁ、ざっと書いちゃったけど、大事なのは以下の部分かな。

    $all_lists = get_posts( array( 'post_type' => get_post_type($post),
                                   'orderby' => 'menu_order',
                                   'order' => 'ASC',
                                   'posts_per_page' => 30));

‘orderby’ => ‘menu_order’
‘order’ => ‘ASC’
で、「ページ属性」の「順序」通りに並び替える。

‘posts_per_page’ => 30
は、まぁ、適当に子ページが30を越えてるなら、50とか100にね。

array_shift($all_lists);
おそらく、親ページの「ページ属性」「順序」は「0」としているはず。
とすると、配列の先頭に親ページがくるので、array_shift()で先頭を取り出してしまう。
(親ページに子ページのリストを表示したいんだから、親ページは不要でしょ?)
もし、「ページ属性」「順序」「0」が他にもあるなら、期待した動作にならないので、要注意。
個人的には、親ページの順序は「0」子ページは「1」から振ってくようにしている。
(ただ、親ページを最初に作っておけば、「0」でも大丈夫みたいだけどね、念のため)

    foreach($all_lists as $post) {
     setup_postdata($post);
    ?>
    <li>
     <a href=”<?php the_permalink() ?>”><?php the_title() ?></a>
    </li>
    <?php
    }
    ?>
   </ul>

あとは、foreachで回して、タイトルとパーマリンクを使ってリストにする。

  <?php else : // 子ページなら投稿記事本文を表示 ?>
   <?php the_content( __( 'Continue reading <span class=”meta-nav”>→</span>', 'twentytwelve' ) ); ?>
   <?php wp_link_pages( array( 'before' => '<div class=”page-links”>' . __( 'Pages:', 'twentytwelve' ), 'after' => '</div>' ) ); ?>
  <?php endif; ?>
  </div><!– .entry-content –>
 <?php endif; ?>

ここは content.php の中身そのままなので、特筆なし。

Excel vba でIEを操作してみる 【 IEがすでに起動しているかどうかの判別 】

Dim ie_obj As Object
Dim ObjShell As Object
Dim ObjWindow As Object
Dim WinExist As Boolean
Dim WinPage As String

WinExist = False
Set ObjShell = CreateObject(“Shell.Application”)
For Each ObjWindow In ObjShell.Windows
  If TypeName(ObjWindow.Document) = “HTMLDocument” Then
    WinExist = True
    Set ie_obj = ObjWindow
    If ie_obj.locationName = “Google” Then
      WinPage = “opend”
    End If
  End If
Next
‘ WinExist、IEが起動していたらTrueにするが、最初はFalse

‘ For Each でウィンドウがある限り繰り返し処理
‘ そのウィンドウのドキュメントタイプがHTMLかどうか
‘ HTMLならIEなのでWinExistにTrueを代入
‘ 見つけたIEをオブジェクトに代入
‘ さらに、そのロケーションネーム(タイトル)がGoogleかどうか
‘ GoogleならWinPageを”opened”にする

WinExist や WinPage なんてのはあってもなくても良いけど、

「IEが起動していなければ立ち上げる」とか
「IEは起動しているけど、目的のページ(タイトル)ではないから移動する」とか

そんな条件分岐に使ったりしても良いかと。

また、「locationName」を「locationURL」とすればURLを取得できるので、特定のURLを探し出したりすることもできる。

他にも

ie_obj.Name
ie_obj.Path
ie_obj.FullName
ie_obj.Width
ie_obj.Height
ie_obj.Left
ie_obj.Top
名前(Internet Explorer と入る)
パス(ディレクトリ名まで)
フルパス(ファイル名まで)
ウィンドウの横幅
ウィンドウの高さ
ウィンドウの左端からの位置
ウィンドウの上端からの位置

といった感じで情報を取得できる。

ランダムな数値を作る Excel、vba、そして算術型or銀行型丸め処理  ついでに、PHP、FileMaker

Excel ワークシート関数
 =round(rand()*(y-x)+x,0)
 これでxからyの間で乱数を作れる。

 例えば、23~37までの乱数を作りたいのなら「 =round(rand()*14+23 」となる。

 rand()は0から1未満の数字になる。なのでrand()*14は0から14未満。そこに23を足す。
 つまり23から37未満。これをround関数で四捨五入すれば、23~37までの乱数が作れる。

 
Excel vbaの関数
 =int(rnd*(y-x+1)+x)
 これでxからyの間で乱数を作れる。

 上の例と同様に23~37までの乱数を作りたいのなら「 =int(rnd*15+23) 」となる。

 で、ここで使われるintは「小数点以下を切り捨てる」と言うとちょっとおかしいのかな。
 「整数部分を取り出す」とか「小数点部分を取り除く」の方が良いのか。

 なので、rnd*15で0から15未満の数を作り、23を足すと、23から38未満の乱数ができる。
 これをintで整数部分を取り出してやれば、23~37の乱数が出来上がり。

 
 さて、vbaではround関数を使わずにint関数を使っているところが多いけど、なんでなんだろ。

 vbaのround関数は確かに、ワークシート関数のroundとは挙動が異なる。

 いや、挙動をしっかり把握していれば、「 =round(rnd*(y-x)+x) 」でも良いと思うよ。
 というか、普通にこっちでも問題ないのでは?

 ただ、vba関数のroundをちゃんと使う場面はなかなかないと思うし、正確に使ってる人はあまりいない。

 vbaのround関数は「銀行型丸め処理」になってるから。
 だから、roundではなくintを使っているところが多いのかも。

 vbaのround関数は簡単にってしまえば、「0.5」とか「3.5」とか「4.5」のような「x.5」となっている時、
 四捨五入するかどうかは結果が偶数になるかどうかで判断される。

 四捨五入の結果が偶数なら切り上げるけど、奇数なら切り捨てて偶数になるようにする。

 「0.5」→「0」、「3.5」→「4」、「4.5」→「4」といったようにね。

 
 ここで、次の数の合計は?

 「0.5」「1.5」「2.5」「3.5」「4.5」「5.5」「6.5」「7.5」「8.5」「9.5」

 はい、50です。

 では、これを四捨五入してから合計してみましょう。

 「1」「2」「3」「4」「5」「6」「7」「8」「9」「10」

 はい、55になります。

 続いて、銀行型丸め処理による四捨五入をしてから合計してみましょう。

 「0」「2」「2」「4」「4」「6」「6」「8」「8」「10」

 はい、50になります。

 ね、なんか、単純に四捨五入するよりも、元の数を合計した値に近くなる。というかこの場合同じになる。

 いくつかx.5な値を選んでワークシート関数的な四捨五入=算術型丸め処理と銀行型のそれとを比べると、
 銀行型の方が、元の数の合計に近くなる傾向にあることがわかる。

 まぁ、そんな特性を必要とする人が、Excelのvbaユーザーに、割合としてそれほど多いとは思えないけど。
 それでも、そんな違いがあるから、みんなintで処理してるのかもしれないね。

 ついでに、vbaのround関数で

 round(1.05,1) とした場合、結果は「1.0」

 round(1.15,1) とした場合、結果は「1.2」

 となる。

 別に「x.5」である必要があるわけではなく、四捨五入をするための比較検討をする数値が「5」であるか
 そこがポイント。

 かりに「5」ではなく、さらに小数点以下が続いていて「5000001」だったら、

 つまり round(1.05000001,1) だったら、この結果は「1.1」になる。

 ややこしいですね。

 でも、四捨五入という処理はわりと日常的に行われているだけに、
 vbaでの round は銀行型だということを覚えておいてそんはないでしょう。

  
 また、どうしてもvbaでワークシート関数のroundを使いたければ、

 WorksheetFunction.Round(xxx.x,y)

 とでもしてください。

 詳しくは http://support.microsoft.com/kb/225330/ja といったMSのサイトで。

 
 

さて、ついでなのでPHPではランダムな値をどう求めるか。

rand( int $min , int $max )

 まんま、ですな。

 rand(23,37)

 これで23~37の乱数が出ます。

 

さらについでで、FileMakerでのランダム。

 Random * (y – x) + x でOK。

 全レコードからランダムにあるひとつのレコードを選ぶ、といったような場合にはこんな感じ。

 Random * Get ( 対象レコード数 ) + 1

 
 

ぶっちゃけ、Excelのワークシート関数も使うしvbaも使うし、PHPもFileMakerも使うのに、ちょっとした適当などうでも良い程度のランダムな値を作るのに、こんなにも作法があるとはねぇ・・・