カテゴリー: ブログ

  • ACCESS VBA ダブルクリックによってクリックイベントの処理が2回実行されてしまう件

    はじめに 

      ある入力画面フォームで登録ボタンを用意、クリックイベントの処理(イベントプロシージャ)でデータベースに登録する処理を割り当てました。運用になってからしばらくは順調に動作していましたが、複数の担当者の内、ある人が操作した時に、データが2重登録されるケースが出現。
     
     
    原因について

     どうやら、その担当者は登録ボタンをダブルクリックしていて、クリックイベント処理が2回走ってしまったことが原因らしい。
    改めてACCESSのヘルプを見直すと、
     
     Form.DblClick イベント (Access)
     https://msdn.microsoft.com/ja-jp/vba/access-vba/articles/form-dblclick-event-access
     
     ■マウス イベントを受け取るオブジェクトに対しては、次の順序でイベントが発生。

       MouseDown ⇒ MouseUp ⇒ Click ⇒ DblClick ⇒ MouseUp 

     ■コマンド ボタンをダブルクリックすると、次の順序でイベントが発生。

       MouseDown ⇒ MouseUp ⇒ Click ⇒ DblClick ⇒ MouseUp ⇒ Click
     
     との事。
     
     今回のケースは、コマンドボタンをDblClickした場合なので、Clickイベントが2回発生した。
     そもそも、DblClickの時にClickイベントが発生する事など、全く考えていなかったので、この仕様には驚いています。ただ、今回の事を知って改めて考えると、パソコンの設定によってDblClickとClickの判断は難しい場合があるのだと思えば、なんとなく納得しています。
     

    対応方法

    2回目のClickイベントを無効にする次の方法で対応します。 
    DblClickイベントプロシージャの引数に「Cancel」があるので、この引数にtrueを設定して終了すれば、以降のClickイベントは発生しません。
     
     例)
     
     Private sub XXXボタン_DblClick(Cancel As Integer)
       Cancel = true
     End sub
     
    おわりに

     入力画面を設計する際、GUIの観点からなるべく入力を簡単にできるよう考えます。
    例えば、テキストボックスをダブルクリックするとデフォルトの値が設定されるようにするとか。
    結果として、クリック操作とダブルクリック操作が混在する画面の操作性の良し悪しは、
    判断が分かれるところですが、今回のようなケースでうっかり操作による誤動作の対応はしておきましょう。

     なお、Accessのヘルプには、
     ”一般的には、コマンドボタンをダブルクリックしない事をお勧めします”
     とありました。

     

  • MS-AccessからODBC経由でFirebirdのテーブルにアクセスは大変

     あるユーザーのシステムで、Ccu労組会計のデータをMS-Accessからアクセスして処理することになりました。それで、ODBC経由で接続することにしたのですが、…私の覚えを兼ねて、ここに書いておきます。

     

    1.ODBCって、マルチバイト文字は正しく処理できない!

    1.1 DBファイル、クライアントdllへのパスにマルチバイト文字があると接続できない

      

      まず、上図のようにしたら、接続時にエラーとなってしまいました。各パスを確認したところ、後ろの方が切れてしまっている。どうも「会計」とあるのがいけないらしい。「会計」は4バイトだけど2文字なので2バイトと判断して、差額の2バイトはカットしてしまうものと思われる。

      これは、英数字と空白だけのフォルダを作って、そこにコピーして事無きを得ました。

     

    1.2 テーブルの中身もマルチバイト文字があると…

      これは、私(平石)ではなく、一緒に仕事をしている組合員が見つけた現象です。

      下図は、RKA23というテーブルの内容を、フリーソフトを使って見たものです。

      

     ところが、同じものをMS-Accessで見ると、データ内容に余計な文字が付加されている。

      (吹き出しは記述者=平石が付けたもの)

      どうも、Shift-JISでのバイト数が項目長と一致するときに、この現象が起きるらしい(このときは、項目長を超えるデータができてしまうかのように見えますが、MS-Accessで見るときの項目長はバイト数ではなくて文字数なので、これらのケースでは、項目長を超えていません)。

      データのShift-JISでのバイト数を求める関数を作り、そのバイト数が項目長を超えている分はカットするようにして、対処できました。

     

    2.DAO.TableDef.Connectを書き換えるとReadOnlyになってしまう

      実は、上記1.1に書いた、「DBファイル、クライアントdllへのパス」については、DAO.TableDef.Connectに、その情報があるので、これを書き換えて対処できるのではないかとやってみたのです。

      読むだけなら、うまく行きました。パスに「会計」などのマルチバイト文字があってもちゃんと読めます(ODBCの設定ではマルチバイト文字の無いパスを指定して、あとから書き換えます)。

      ところが、内容を更新しようとすると、ReadOnlyである旨のメッセージが出てダメでした。

  • 画像の「赤」と「青」を入れ替えるプログラムを作ってみた

     実は私、赤信号を見ると、青信号であると確信して道路を渡ってしまう人です。
     先だって、たまたま「色彩心理学入門」なる本を読んで、その原因と思われるものが分かりました。
     私の理解では、「正常者」つまり色覚についての多数派の方は、実は「青緑色弱」と呼ぶべきであって、赤と緑の区別はつくらしいが、青と緑の区別はほとんどつかないらしい。
     そこで、もしかしたら、「赤」と「青」を入れ替えたら、彼ら青緑色弱者の気持ちが少しはわかるのではないかと思い、そんなプログラムを作ってみました。

     

     上の画像は、近所のお宅の何とか赤く見える花を撮ったものと、それの「赤」と「青」を入れ替えたものを並べました(クリックしてみてください)。
     左は撮ったままの画像ですが、「いったいどこに花なんかあるんだっ」という感じで、まったく花の存在はわかりません。
     右を見ると、花の存在ははっきりわかります。実は、この右の画像を見るまで、こんなにたくさん花が咲いていることに、まったく気づきませんでした。やはり「正常者」の方が正常なようです。

     そんな訳で、良いプログラムを作ったと自負しております。

  • jQueryを使って、EnterキーでTab移動する

    はじめに

    システム開発の際、GUIの要件の1つに、「入力項目は、Enterキーで確定し、次の入力項目に移動すること」を挙げている事が、経験として結構あります。Webシステムにおいても、例外では無くて、以前からあった方法として、Javascriptのコーディングで
    event.keyCodeプロパティを、強制的にEnterキー(13)からTabキー(9)に入れ替えてしまう方法があります。

    if (event.keyCode == 13){
        event.keyCode = 9;
    }
    

    但し、InternetExpoler Ver.9以降は、event.keyCodeプロパティの強制的な変更が出来なくなっており、 (セキュリティ対策と思われる)この方法は使えません。

    そこで、どうしたものか?Google先生に聞いてみると、どうやらjQueryを使うと出来るらしいという事で、次のサイト「[jQuery] Enterキーでフォーカスを移動するには」を、参考にさせていただきまして、自分用にカスタマイズした関数「fEnterChangeTab()」を紹介します。

    1.関数の仕様
    ・input要素の中で、button型、hidden型、readonly属性、disabled属性は、タブ移動先から除外する事。
    ・画面最後のinput要素でEnterキーを押されたら、最初のinput要素に移動する事。
    ・画面最初のinput要素でEnterキー+Shiftキーを押されたら、最後のinput要素に移動する事。

    2.javascriptコーディング例

    // ①jQueryの取り込み
    <script type="text/javascript" src="(パス)/jquery-1.10.2.js"></script>
    
    <script type="text/javascript">
    <!--
    // input項目をEnter キー、Shift+Enterキーでtab移動 without(button, hidden) 
    function fEnterChangeTab(){	
    
      // ② input要素の選択。但し、ボタンとhidden型は除く。
      var oObject = "#Div要素のid :input:not(:button):not(:hidden)";
    	
      $(oObject).keypress(function(e) { 
        var c = e.which ? e.which : e.keyCode; // クロスブラウザ対応
        if (c == 13) {  
            var index = $(oObject).index(this); // indexは0~
            var cNext = "";
            var nLength = $(oObject).length;
            for(i=index;i<nLength;i++){
                cNext = e.shiftKey ? ":lt(" + index + "):last" : ":gt(" + index + "):first";
                // ③ 止まってはいけいない属性 readonly
                if ($(oObject + cNext).attr("readonly") == "readonly") {
                    if (e.shiftKey) index--; // 1つ前
                    else index++;            // 次へ
                }
                // ③ 止まってはいけいない属性 disabled
                else if ($(oObject + cNext).prop("disabled") == true) {
                    if (e.shiftKey) index--; // 1つ前
                    else index++;            // 次へ
                }
                else break;
            }
            if (index == nLength - 1) {
                if (! e.shiftKey){
                    // 最後の項目なら、最初に移動。
                    cNext = ":eq(1)";
                }
            }
            if (index == 0) {
                if (e.shiftKey) {
                    // 最初の項目なら、最後に移動。
                    cNext = ":eq(" + (nLength - 1) + ")";
                }
            }
            $(oObject + cNext).focus();           
            //e.defaultPrevented; ⇒ 2018.06.28 このプログラミングは間違い。
            e.preventDefault()    //規定の動作をキャンセルするため、こちらのメソッドを呼ぶ。
        }  
      }); 
    } 
    
    // ④onloadのタイミングでこの関数を実行
    if(window.attachEvent){
        // IE用
        window.attachEvent('onload',fEnterChangeTab);
    }
    else if (window.opera){
        // opera用
        window.addEventListener('load',fEnterChangeTab,false);
    }
    else {
        // Mozilla用
        window.addEventListener('load',fEnterChangeTab,false);
    }
    // -->
    </script>
    
    

    [説明]
    ① jQueryの取り込み
    (パス)は適宜、環境に置き換えて下さい。jQueryはなるべく最新を取り込んだ方が良いと思います。
    ②input要素の選択。但し、ボタンとhidden型は除く。
    jQueryのセレクタを使って、対象とするinput要素の項目だけを選択します。
    また、今回は、<div></div>で囲まれた範囲(#Div要素のidを指定)のinput要素を対象としています。

    ③止まってはいけいない属性
    readonly属性、disabled属性のinput項目は、この条件で判断して除外します。

    ④onloadのタイミングでこの関数を実行
    画面要素が取り込まれたタイミングで、対象とするinput要素に適用させます。
    因みに、クロスブラウザ対応のコーディング例。

     

    3.input要素が動的に追加された時の対応
    入力の操作で、input要素(入力項目)が動的に追加されるケースがある場合、
    追加されたタイミングで、この関数を呼んでkeyPressイベント関数をリビルドします。
    そうすることで、追加したinput要素を適用対象と認識させます。

     

    今回はこれにて、以上。

  • 検索機能付きのセレクトボックス。jQueryのSelect2を使ってみる

    はじめに
    選択肢がたくさんあるセレクトボックスは、選ぶ時、縦に広がったボックスから見つけるのに苦労します。自前で絞り込みができる方法を考える前に、ネットで探してみたら、やっぱりありました。jQueryプラグインのSelect2です。このjQuery Select2は、ボックス内の検索、タグ付け、ajaxリクエストによるセレクト項目の設定等が出来て、Bootstrapテーマで簡単に実装できるセレクトボックスです。今回、JavaScriptのDOMを使って、セレクトボックスをHTMLページに動的に追加した際、つまづいた事があったので、そのメモ書きです。

    概要
    DOMでセレクトボックスを追加したら、その後、『$(‘select’).select2();』を実行しておくこと。 そうしないと、select要素がselect2で初期化されない。

    例)「好きな果物」セレクトボックス 追加ボタン付き

    select画像1
    select画像1

    1.ダウンロード
    ・seletc2
    https://select2.github.io/
    ・select2 bootstrapテーマ
    https://github.com/select2/select2-bootstrap-theme

    2.select2とbootstrapの準備
    jsとcssを取り込みます。

    <link href="(パス)/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
    <link href="(パス)/css/select2.min.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></></script>
    <script type="text/javascript" src="(パス)/js/bootstrap.min.js"></script>
    <script type="text/javascript" src="(パス)/js/select2.min.js"></script>
    

    (パス)は適宜、環境に置き換えて下さい。jQueryはなるべく最新を取り込んだ方が良いと思います。

    3.DOMによるselect要素の追加操作

    コーディング例です。

    (1) html

    <table align=left>
     <tr>
      <td  style="width:100px;height:30px;text-align:center;background-color: #ffffff;border:1px solid #000000;" >
       <span>好きな果物</span>
      /td>
      <td style="width:200px;height:30px;text-align:center;background-color: #ffffff;border:1px solid #000000;" >
       <select class="select" name="cSelFruit_1" id="cSelFruit_1" >
        <option value="0" selected>  </option>
        <option value="1" >バナナ</option>
        <option value="2" >イチゴ</option>
        <option value="3" >メロン</option>
        <option value="4" >リンゴ</option>
        <option value="5" >グレープフルーツ</option>
       </select>
      </td>
      <td nowrap align=center><button type="button"  id="btnInsert_1" onClick="fOnClickInsert(this);"  >追加</button></td>
     </tr>
     <tr id="InsertLineEnd"></tr>
    </table>
    
    <!--追加行ひな型 ここから -->
    <table  style="visibility:hidden;" id="masterDefault">
     <tr id="II_prototype">
      <td  style="width:60px;height:30px;text-align:center;background-color: #ffffff;border:1px solid #000000;" >
       <span>好きな果物</span>
      </td>
      <td style="width:60px;height:30px;text-align:center;background-color: #ffffff;border:1px solid #000000;" >
        <select name="cSelFruit" id="cSelFruit" >
         <option value="0" selected>  </option>
         <option value="1" >バナナ</option>
         <option value="2" >イチゴ</option>
         <option value="3" >メロン</option>
         <option value="4" >リンゴ</option>
         <option value="5" >グレープフルーツ</option>
        </select>
      </td>
      <td nowrap align=center><button type="button"  id="btnInsert" onClick="fOnClickInsert(this);"  >追加</button></td>
     </tr>
    </table>
    <!-- ひな型 ここまで-->
    

    (2) javascript

    // ①静的に実装されているセレクトボックスの初期化
    $(function(){
     $('.select').select2();
    });
    
    // select要素の追加 
    function fOnClickInsert(oPara){
    // 操作した行番号を取得  oPara.id 例) "cSelFruit_1"
     var aWork = oPara.id.split("_");
     var nLineNo = aWork[aWork.length - 1];
    
    // ひな型行オブジェクトの取得
     var oLine1 = document.getElementById("II_prototype");
    
    // 追加する行オブジェクトを作成する
     var oNewLine1 = oLine1.cloneNode(true);
    
     var oNewLine_td = "";
     var oNewLine_select = "";
    
    // ここから属性情報設定
     var nNewLineNo = parseInt(nLineNo) + 1;
    
    // td,button,select情報の設定
     oNewLine_button = oNewLine1.getElementsByTagName("button");
     oNewLine_select = oNewLine1.getElementsByTagName("select");
    
    // ボタン
     for (i=0;i<oNewLine_button.length;i++){
      if(oNewLine_button.item(i).id == "btnInsert"){ // 追加ボタン
       oNewLine_button.item(i).id   = "btnInsert_" + nNewLineNo;
      }
      else {
       continue;
      }
     }
    // セレクトボックス
     for (i=0;i<oNewLine_select.length;i++){
      if(oNewLine_select.item(i).id == "cSelFruit"){	// 好きな果物
       oNewLine_select.item(i).id   = "cSelFruit_" + nNewLineNo;
       oNewLine_select.item(i).name = "cSelFruit_" + nNewLineNo;
    
       // ②classはここで設定しないと、効かない。
       oNewLine_select.item(i).className = "select"; 
      }
      else {
       continue;
      }
     }
     // 行追加
     oAfterLine = document.getElementById("InsertLineEnd");
     oAfterLine.parentNode.insertBefore(oNewLine1,oAfterLine);
     
     // ③ここで動的に追加したセレクトボックスの初期化
     $('.select').select2();	
    
     return;
    }

    ①のセレクトボックスの初期化は、ロードされた時点で実装されているselect要素に対して、適用されます。
    ②のクラス設定は、このタイミングで設定しないとうまく効きません。
    ③のタイミングで、直前に追加したselect要素がselect2に初期化されます。

    4.追加ボタンを押した結果

    select画像2
    select画像2

  • ACCESSのフォームでSQLServerのテーブルを更新したら『データの競合』エラーが発生

    1.事象
     ACCESSの単票フォームのレコードソースとしてSQLServerのテーブルを指定している。「Microsoft SQL Server Manager」を使い、このテーブルに次のような列を追加して、フォームで更新操作をしたらエラーが発生。

    追加した列: A項目  bit型  null可

    エラーメッセージ:データの競合

    “このレコードは他のユーザーによって変更されています。[レコードの保存]を選択すると、他のユーザーによる変更を無視し、自分が行った変更を反映します。[クリップボードにコピー]を選択すると、変更したデータはクリップボードコピーされ、他のユーザによる変更が反映されます。必要に応じて、クリップボードのデータを張り付け、自分が変更したデータに戻すこともできます。”

    なお、このエラーが出た時、もちろん操作をしているのは、自分だけです。

    2.対処と原因

    [対処]

     A項目 bit型 null可   →   A項目 bit型 null不可 (必須項目、初期値:0)

     nullを許容しない、必須項目とする事でエラーを回避しました。

    [原因]
     はっきりした原因は不明。ネットで検索した対処方法によると、どうやら、ACCESSでリンクする場合、bit型のようなBOOL属性の項目は、必須項目にしないとダメなようです。裏でどんな動きをして、今回のようなエラーが発生してしまうのか。

     以下、思った事。

     bit型は、ACCESSのデータ型ではYes/No型になります。ACCESSのフォームにおいて、チェックボックスの値を格納する時のデータ型として、よく利用します。なので、データはYESかNOかの2択で、nullはありません。今回、該当のテーブルは、元々、ACCESSのmdbのテーブルで、ACCESSのアップサイジング機能を利用してSQLServerのテーブルに変換したテーブルです。追加した列のプロパティは、そのテーブルにおいて既存のbit型列にならって設定しました。既存のbit型列は"null可"になっていました。同じように設定して、結果、エラーが起きました。改めて既存のbit型列のプロパティを見直したところ、拡張プロパティが設定されていたので、全て同じように設定しました。

    例えば、次の拡張プロパティ

    AllowZeroLength : False
    AppendOnly: False
    Attributes:1
    CollatingOrder:1041
    DataUpdatable:False
    MS_Format:Yes/No
    etc..(拡張プロパティは18項目あり)

     これらを設定しても、状況は変わりませんでした。さて、なんだろう。

     アップサイジング機能で変換されたbit型の列は、nullを許容する設定でしたが、既存レコードには値が全て設定されていました。後で、「Microsoft SQL Server Manager」で追加したbit型の列は、既存レコードにnull値が設定された状態になり、システム側で強制的に値を設定しようとして、結果的にその動作が競合となりエラーになってしまったのでしょうか。
    (根拠なし、想像です)

    以上

  • 『Googleニュース用RSSジェネレータ』で収集したニュースをPHPで編集・成形してWebサイトに表示する

      このブログで以前に紹介した“『Googleニュース用RSSジェネレータ』と『単眼RSS』を使って労働関連に関る最新ニュースのコンテンツを作る”の続編です。 ニュースの表示方法をもう少しカスタマイズしたくなったので、単眼RSSを使わないやり方で編集する方法を模索しました。以下を紹介します。
     
    [概要]
    ・googleニュースをPHPのSimpleXML拡張モジュールを使ってXMLオブジェクトに変換、さらにarray型データに変換する
    ・array型データの中から、Webサイトの表示に必要な項目を取り出して、htmlドキュメントを成形する

      
    1.googleニュースをPHPのSimpleXML拡張モジュールを使ってxmlオブジェクトに変換、さらにarray型データに変換する


     SimpleXML拡張モジュールは、php5.0.1以上から対応しているので、最近のレンタルサーバなら殆ど利用できると思います。まず、Googleニュース用RSSジェネレータ<http://g.1o4.jp/news-rss.html>でURIを生成します。そのURIで得たデータをSimpleXMLElement、SimpleXMLIteratorを使ってarray型に変換します。というような操作が、phpマニュアルサイトの「User Contributed Notes」のコーディング例 http://php.net/manual/ja/class.simplexmliterator.phpで紹介されていましたので、参考にしました。
      
    その例の中にあるxml2array()関数を使用した場合。

    [PHP コーディング例]  

    [crayon lang=”php”]
    // 例:uriは労働運動関連ニュースを10件取得する場合
    $uri = “https://news.google.com/news?ned=us&ie=UTF-8&oe=UTF-8&q=%E5%8A%B4%E5%83%8D%E3%80%80%E9%9B%87%E7%94%A8&output=atom&num=10&hl=ja”;
    // この関数は、コーディング例にあるユーザ関数です。詳細は、上記のphpマニュアルサイトのリンク先で確認してください。
    $rssAtomArray = xml2array($uri);
    [/crayon]

      
    2.array型データの中から、Webサイトの表示に必要な項目を取り出して、htmlドキュメントを成形する

    [php コーディング例]

    [crayon lang=”php”]
    $aWork = array(); // Webサイト表示に必要な項目のみ、取り出して保持しておく領域
    $aSortKey = array();// ソート用

    // Webサイトの表示に必要な情報だけを取り出す
    foreach ($rssAtomArray[“entry”] as $row){
    $jpDate = new DateTime($row[“updated”][0]);
    $jpDate->setTimezone(new DateTimeZone(“Asia/Tokyo”));
    array_push($aWork, array(“updated” => $jpDate->format(“Y/m/d H:i:s”), “title” => $row[“title”], “id”=> $row[“id”]));
    array_push($aSortKey, $jpDate->format(“Y/m/d H:i:s”));
    }
    array_multisort($aSortKey, SORT_DESC, $aWork); // ニュースは、更新日時の降順でソート。

    // html成形
    $cHTML = “

    “;
    foreach($aWork as $row) {
    $cHTML .= “

    “;
    $cHTML .= “

    “;
    $cHTML .= “

    “;
    }
    $cHTML .= “

    “.$row[“updated”].”
    “.$row[“title”][0].”

    “;
    echo $cHTML; // ブラウザに表示
    [/crayon]

    [説明]
    googleニュースで得たarrayデータの要素(=xmlのタグ)

    ・"updated" :ニュースの更新日時。atom(RFC3339) 形式の世界標準時だったので日本時間に変換
    ・"title" :ニュースのタイトル
    ・"id" :ニュースのリンク先情報

    これらの要素は、1.の処理の$rssAtomArrayをprint_r()で出力して、確認しました。
    今回は、googleニュースの場合ですが、他のxmlオブジェクトは、違ってくるかもしれません。
    後は、Webサイトに合わせて、htmlドキュメントを成形して、表示すればOKです。

    余談:
    XMLオブジェクトをArray型に変換する方法は、ネットで検索すると、json_decode、json_encodeを利用すると簡単にarray型に変換できる、と出てきます。試してみると、googleニュースで取得したデータは、階層が深いのか?うまく変換できませんでした。今回、紹介したSimpleXML拡張モジュールには、イテレータが用意されているので、それを使えばXMLオブジェクトのハンドリングは容易になりますね。
    (結局、phpマニュアルサイトのコーディング例を参考にしちゃうんですが)

  • BlenderでモデリングしたワイヤーフレームをFlashで描画再生してみる。

    はじめに

      今回の思いつきは、『Webサイトのコンテンツで、多面体のワイヤーフレーム画像を動かしたい。』です。幾つか実現方法はあると思うのですが、Blenderでモデリングを行い、そこで作られた頂点座標情報を取り込んでflashで再生する、という方法を選びました。
     
    1.Blenderでモデリング
       Blenderは、オープンソースの3次元CG開発ソフトウエア(統合開発環境)ですね。だいぶ前に同様のCGソフトのMetasequoiaで何かやろうとチャレンジした事があったのですが、挫折しました。そこでBlenderです。使い方は、次のサイトを参考にさせて頂きました。
    「Blender入門」(http://www.blender3d.biz/)大変感謝しています。

     以下、何とかリンゴをモデリング。

    blender
     

     

     

     


    2.頂点座標情報の取り込み
      モデリングしたリンゴの頂点座標情報の取り込みは、BlenderのExport機能で情報をファイル出力して、そのファイルから読み込む事にしました。幾つかあるファイルフォーマットの中から、Wavefront(.obj)フォーマットを選択。 このフォーマットで出力された3Dモデルデータが一番扱い易いと判断しました。 Wavefrontフォーマットの説明は、次のサイトを参考にさせて頂きました。
    「OBJファイルフォーマット」(http://www.hiramine.com/programming/3dmodelfileformat/objfileformat.html)
    大変感謝しています。
     OBJファイルフォーマットは、頂点座標値(x,y,z)データ、多面体の面(メッシュ)を構成する頂点座標を指すインデックス情報や、モデリングした時の法線ベクトルの情報等が含まれています。今回は、頂点座標値(x,y,z)データ、多面体の面(メッシュ)を構成する頂点座標を指すインデックス情報を利用します。
      
    3.flashで再生する
      objファイルを読み込んで描画するプログラムをAS3.0でコーディング。AS3.0を選んだのは、ブラウザ上で画像を操作できるインターフェース(各種イベントを拾える)が用意されている点がいいと思ったから。 AS3.0のコーディングは、次の本を参考にさせて頂きました。
    「C++による簡単実習 3次元CG入門」(http://www.morikita.co.jp/books/book/2149)
    言語はC++ですが、AS3.0でプログラミングする際に大変役に立ちました。
     [ワイヤーフレーム]

     wire

     
     

     

     

     

     

     

     

     

    [面を塗りつぶし  ]

    apple apple2

     

     

     

     

     

     

     

     

     

    今回はここまでです。

     

  • タスクイメージは破損しているか、または変更されています。(HRESULTからの例外:0x80041321)

    1.事象
     Windows7のパソコンにおいて、タスクスケジューラで毎日実行していたバックアップ処理が出来ていない事が発覚。とりあえず、実行記録を確認しようとタスクスケジューラを起動したらタイトルのエラーが発生。エラーメッセージの応答で[OK]をするが、引き続き同じメッセージが表示される。
    この操作は数十回繰り返した。おそらく、設定されていた多くのタスクに対してメッセージが表示されたと考えられる。バックアップ処理が出来ていなかったのは、このタスク設定が壊れてたためと断定。

    2.原因調査と対処
     とりあえず、タスクスケジューラの設定を元通りにする対処方法をネットで検索。同様の事象は過去にも結構出ているらしい。以下のサイトを参考に対処してみる。

      タスクスケジューラを開くとエラーメッセージが表示される「タスクスケジューラサービスが利用できません」
      http://answers.microsoft.com/ja-jp/windows/forum/windows_7-performance/%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%B9%E3%82%B1/fde068e5-d1d5-4821-9888-b2270a428e6f?auth=1


     [対処: ”タスクのインポート”操作でタスクの再設定]
     C:\Windows\System32\Tasksフォルダ配下の全ファイルを任意の場所に移動してタスクスケジューラを起動。エラーは出なくなった。ここから、全部のタスクをインポートで再設定することにした。TasksフォルダにはWindowsやパソコンベンダー等のフォルダ配下に100を超える設定ファイルがある。気が滅入りながらちびちびやっていると、設定ファイルのタイムスタンプで気づきが・・。どうやらバックアップ処理が失敗した日の直近で更新されている設定ファイルが破損しているらしい。まず、設定ファイルのタイムスタンプをみてインポートしないで元に戻せるか判断。これでだいぶ楽になった。

     [タスクイメージが破損した原因(多分): Windows10->Windows7のダウングレード]

     しかし、以下のエラーが発生してインポート操作で復旧が出来ないタスクが出てきた。


     “タスクの形式が有効ではありません。(2,8):version:1.5”
     

     ネットを検索。以下が参考になりました。

      タスクスケジューラーで「タスクの形式が有効ではありません」と表示され作成できない
      http://answers.microsoft.com/ja-jp/windows/forum/windows_7-update/%E3%82%BF%E3%82%B9%E3%82%AF%E3%82%B9%E3%82%B1/b20e1938-22ee-4fce-8f71-db4fa66dcf50?auth=1

     確かに、破損している設定ファイルのタイムスタンプは、Windows10からWindows7に戻したタイミングと一致している!
     おそらく、元に戻す課程で破損してしまったのではなかろうか。但し、 原因が分かったところで、戻せないタスクがあるってことは問題だな。そのタスクが何をやっていたのかも分からないし。
     
      Microsoftめー、またやってくれたなー。

     おそらくWindows10にしてから元のOSに戻したパソコンは、こうなっている可能性が大。 一度、タスクスケジューラを起動して確認してみることをお勧めします。

     

  • jQueryのAjaxリクエスト(POST)で日本語の送信データが文字化け

    ブラウザ側入力フォームで指定した日本語文字列をAjaxリクエスト(POST)でサーバに渡した際、サーバ側で参照したら文字化けを起こしていてハマりました。

    jQuey日本語リファレンスをみると、サーバに送信するデータはクエリー文字列に変換されてGETリクエストとして付加されるとあったので、URLエンコードは自動的にやってくれると思いましたが、POSTの場合はこちらで変換した値を指定してあげないとダメなようです。
    以下、サンプル。日本語が入力されている「cSearchKeyWord」をencodeURIで変換してdata:{・・・・}に指定してます。

     var cSearchKeyWord = encodeURI(document.form001.cSearchKeyWord.value.trim());
     $.ajax({
      type:"POST",
      url:"送信URL",
      dataType:"html",
      data:{
       "cSearchKeyWord":cSearchKeyWord,
       "cHashTags":cHashTags,
       "cFromID":cFromID,
       "cToID":cToID,
       "nRetweetFlag":nRetweetFlag,
       "cGetCount":cGetCount
      }
     }).then(
      // 通信成功
      function(data,status,xhr){
      ・・・・
      },
      // 通信失敗
      function(xhr,status,error){
      ・・・・
      }
     );
     
    この結果にたどり着くまで、えらい時間が掛ってしまいました。phpのmb_stringとかhtmlの文字コード設定やら、php.iniの文字コードに関わる設定とかを改めて見直しました。結局、中途半端な知識で仕事をしてきているからハマると一から調べなおす事になってしまう。ネットで検索できて便利なのだけど、頭にちゃんと入らないんですよね。いかんなぁ・・・・。