none
クリスタルレポートでの全半角判定、または文字列のバイト数取得方法について RRS feed

  • 質問

  • 環境
    OS = Win7 Pro
    DB = SQL Server 2014
    開発環境 = Visual Studio 2015 Pro
    クリスタルレポートOEM版のバージョン = CRforVS_13_0_21


    いつもお世話になっております。

    状況

     ・クリスタルレポートにて、幅が100バイト分、5行程度表示できるオブジェクトを配置しています。
     ・表示したい文字列はDBから取得しています。
     ・データは、全半角混在しており、「数字:(コロン)全半角混在文字列」の法則で、カンマ区切りで登録されています。

    やろうとしている事

     100バイトに到達して、クリスタルレポートで中途半端な文字で自動改行される前に、
     文字列のバイト数を計算して、きりの良い場所で改行文字を挿入しようとしております。

    ご教示いただきたい事

     クリスタルレポートの書式エディタに記載する為、
     クリスタル構文での全角、半角判定やバイトの取得方法をご教示下さい。


    以上、何卒宜しくお願い申し上げます。

    2017年12月26日 0:49

回答

  • 自分なら逆に考えて、改行してもいい全ての箇所にゼロ幅スペース(U+200B)を挿入しますね。
    そうしておけばテキストオブジェクトがどんな幅に指定されていても自動改行が処理してくれますから。
    それでも望むような状態にならないなら限界として諦めますが。

    切りの良い場所を判定するロジックを作れるなら、挿入位置をしていすることは簡単でしょう。

    #NBSPはだめっぽい?


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク kong0214 2017年12月26日 7:10
    2017年12月26日 3:59
  • 直接の回答ではありませんが、実現の方向性として、一旦プログラムでデータを受け取り、そこで加工してデータテーブルを作成してそこに入れ、それをクリスタルレポートで表示するのではダメなのでしょうか? この方法だといかようにもなります。
    この先、このような案件に出会った際にも、このような方法を取っていれば、それほど悩まずに実現できる可能性が高くなると思います。
    以前、QRコードの表示の件で質問されていましたが、QRコードのイメージを作成し、データテーブルに入れれば、同じように表示できます。

    ちなみに、100バイト分の幅を取ったとしても必ず100バイトで改行されるわけではありません。クリスタルレポートが独自のロジックで改行してしまいます。USP10.DLLのバージョンが関係している情報がありましたが、結局、私は諦めました。
    それとも、現在は改善されているのでしょうか?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kong0214 2017年12月26日 7:10
    2017年12月26日 1:32
    モデレータ

すべての返信

  • 直接の回答ではありませんが、実現の方向性として、一旦プログラムでデータを受け取り、そこで加工してデータテーブルを作成してそこに入れ、それをクリスタルレポートで表示するのではダメなのでしょうか? この方法だといかようにもなります。
    この先、このような案件に出会った際にも、このような方法を取っていれば、それほど悩まずに実現できる可能性が高くなると思います。
    以前、QRコードの表示の件で質問されていましたが、QRコードのイメージを作成し、データテーブルに入れれば、同じように表示できます。

    ちなみに、100バイト分の幅を取ったとしても必ず100バイトで改行されるわけではありません。クリスタルレポートが独自のロジックで改行してしまいます。USP10.DLLのバージョンが関係している情報がありましたが、結局、私は諦めました。
    それとも、現在は改善されているのでしょうか?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク kong0214 2017年12月26日 7:10
    2017年12月26日 1:32
    モデレータ
  • 自分なら逆に考えて、改行してもいい全ての箇所にゼロ幅スペース(U+200B)を挿入しますね。
    そうしておけばテキストオブジェクトがどんな幅に指定されていても自動改行が処理してくれますから。
    それでも望むような状態にならないなら限界として諦めますが。

    切りの良い場所を判定するロジックを作れるなら、挿入位置をしていすることは簡単でしょう。

    #NBSPはだめっぽい?


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク kong0214 2017年12月26日 7:10
    2017年12月26日 3:59
  • いつもお世話になっております。

    今回のシステム開発では
    クリスタルレポートと親和性のあるパッケージソフトからの直接呼出しを想定している為、
    Webフォーム等を挟まずに開発する予定です。

    その為、難儀しております。


    USP10.DLLにつきましては、意識しておりませんでした。
    今後の開発において、意図しない箇所で改行されるようでしたら、
    その時に改めて検討したいと存じます。

    情報有難う御座います。

    2017年12月26日 6:55
  • いつもお世話になっております。

    ゼロ幅スペースにつきましては、初めて知りました。
    凄く有効かもと思いましたが、画面系のデータ登録側と帳票開発側で
    会社が分かれており、相手にゼロ幅スペースの挿入をお願いするのは
    要調整となります。

    もし、私のほう(帳票開発側)でなんともならない場合、
    しかも絶対に意味ある単位で改行を行わないといけない場合に限り、
    協力会社に相談してみようと思います。

    情報有難う御座いました。

    2017年12月26日 7:00
  • いつもお世話になっております。

    下記のプログラムをクリスタルレポートのカスタム関数として
    作成し、問題を解決致しましたので御報告致します。

    //maxLength = 最大文字列幅
    //paramData = カンマ区切りの文字列データ
    Function (Numbervar maxLength,Stringvar paramData)
    (
        local Numbervar targetByteTotal := 0;
        local Numbervar i := 0;
        local Stringvar returnData;

        //カンマ区切りにした場合の配列数を取得
        local Numbervar cnt := Count(Split(paramData,","));

        //配列は「1」から始まる
        For i := 1 to cnt do
        (
            local Numbervar j :=1;
            local Numbervar getAsc :=0;
            local Numbervar targetByte := 0;
            local Numbervar targetLength := 0;
            local Stringvar temp := "";
            local Stringvar target = "";

            //文字列数を取得
            targetLength := Length(Split(paramData,",")[i]);

            //対象文字列
            target := Split(paramData,",")[i];

            //1文字目~最後まで   
            For j := 1 to targetLength do
            (

                //1文字ずつ取得
                temp := Mid(target,j,1);

                //文字コード取得
                getAsc := Asc(temp);

                if getAsc < 256 and getAsc > -1 then
                (
                    //0~255の範囲内であれば、1バイト文字
                    targetByte := targetByte + 1;
                )
                else
                (
                    //0~255の範囲内でなければ、2バイト文字
                    targetByte := targetByte + 2;
                )
            );

            //文字列数 + 「カンマ」分追加
            targetByteTotal := targetByteTotal + targetByte + 1;

            //オブジェクトの表示文字幅数を超えているか?
            if targetByteTotal > maxLength then
            (
                //表示文字列幅を超えている場合、改行文字を間に挟む
                returnData := returnData & Chr(10) & Chr(13) & target & ",";

                //改行文字挿入後に新たに追加した文字列数とカンマ一文字分を格納
                targetByteTotal := targetByte + 1;
            )
            else
            (   
                //表示文字列幅を超えていない場合、追加
                returnData := returnData & target & ",";

                //何故か数字を格納する処理を入れないとコンパイル(保存)ができない為、意味はないが、記載
                targetByteTotal := targetByteTotal;
            )
        );
        //最後のカンマを除いて返す
        returnData := Mid(returnData,1,length(returnData) -1);
    )

    2017年12月26日 7:10