2013年10月16日水曜日

vTigerCRMのレポート機能のExcel出力の文字化けを直す その2

vTigerCRMのレポート機能のExcel出力の文字化けを直す その1」の続きです。

vTigerCRM5.4のReport機能からのExcelファイルを出力した場合に、一つのセルに対して255文字以上の文字が設定されているとExcelファイルを開く際に「ファイルエラー:データが失われた可能性があります。」と出力されることがわかりました。


実際どうデータが失われているのかを確認すると、問題の原因となっているセルがなんと空になっています。
これは非常に困まりました。。。

vTiger5.4に組み込まれているExcelファイル作成のライブラリを直接修正を試みましたがかなり込み入っているため修正は難しそうです。

そういえばvTigerCRM6ではどうなっているんだろとβのソースを確認したところ、「なんと!」というか「やっぱり」というか別ライブラリを採用しています。
そしてvTigerCRM6のデモにて文字長やWindwos固定文字等問題が発生するパターンを確認したところなんと問題なく出力できることがわかりました。

そんなわけでvTigerCRM5.4にvTigerCRM6のExcel出力ライブラリを移植を試すことにします。

なにか大がかりなことをしてるように見えますが、この問題、CRM TOUCHを導入いただいているお客様からのご指摘となるため私としては必死です。

最終的にはTigerCRM5.4のライブラリを修正するより、vTigerCRM6のExcelライブラリを移植したほうが今後のリスクが少ないという判断で実施しております。

なにやら荒療治を行うように聞こえますがやってみるとそうでもありません。

修正対象のソースは/modules/Reports/ReportRun.phpのwriteReportToExcelFile functionです。
writeReportToExcelFile自体への引数は、5.4も6も現時点では同じです。
そのロジックに関しても根本的には変わらず、あくまで新しいライブラリのAPIの使い方が異なる、といった感じです。

そのためwriteReportToExcelFileを6のものとまず入れ替えてしまいます。

function writeReportToExcelFile($fileName, $filterlist='') {

  global $currentModule, $current_language;
  $mod_strings = return_module_language($current_language, $currentModule);

  require_once("libraries/PHPExcel/PHPExcel.php");

  $workbook = new PHPExcel();
  $worksheet = $workbook->setActiveSheetIndex(0);

  $arr_val = $this->GenerateReport("PDF",$filterlist);
  $totalxls = $this->GenerateReport("TOTALXLS",$filterlist);

  $header_styles = array(
    'fill' => array( 'type' => PHPExcel_Style_Fill::FILL_SOLID, 'color' => array('rgb'=>'E1E0F7') ),
    //'font' => array( 'bold' => true )
  );

  if(isset($arr_val)) {
    $count = 0;
    $rowcount = 1;
            //copy the first value details
            $arrayFirstRowValues = $arr_val[0];
    array_pop($arrayFirstRowValues);      // removed action link in details
    foreach($arrayFirstRowValues as $key=>$value) {
      $worksheet->setCellValueExplicitByColumnAndRow($count, $rowcount, $key, true);
      $worksheet->getStyleByColumnAndRow($count, $rowcount)->applyFromArray($header_styles);

      // NOTE Performance overhead: http://stackoverflow.com/questions/9965476/phpexcel-column-size-issues
      //$worksheet->getColumnDimensionByColumn($count)->setAutoSize(true);

      $count = $count + 1;
    }

    $rowcount++;
    foreach($arr_val as $key=>$array_value) {
      $count = 0;
      array_pop($array_value);  // removed action link in details
      foreach($array_value as $hdr=>$value) {
        if($hdr == 'ACTION') continue;
        $value = decode_html($value);
        // TODO Determine data-type based on field-type.
        // String type helps having numbers prefixed with 0 intact.
        $worksheet->setCellValueExplicitByColumnAndRow($count, $rowcount, $value, PHPExcel_Cell_DataType::TYPE_STRING);
        $count = $count + 1;
      }
      $rowcount++;
    }

    // Summary Total
    $rowcount++;
    $count=0;
    if(is_array($totalxls[0])) {
      foreach($totalxls[0] as $key=>$value) {
        $chdr=substr($key,-3,3);
        $translated_str = in_array($chdr ,array_keys($mod_strings))?$mod_strings[$chdr]:$key;
        $worksheet->setCellValueExplicitByColumnAndRow($count, $rowcount, $translated_str);

        $worksheet->getStyleByColumnAndRow($count, $rowcount)->applyFromArray($header_styles);

        $count = $count + 1;
      }
    }

    $rowcount++;
    foreach($totalxls as $key=>$array_value) {
      $count = 0;
      foreach($array_value as $hdr=>$value) {
        $value = decode_html($value);
        $worksheet->setCellValueExplicitByColumnAndRow($count, $key+$rowcount, $value);
        $count = $count + 1;
      }
    }
  }

  $workbookWriter = PHPExcel_IOFactory::createWriter($workbook, 'Excel5');
  $workbookWriter->save($fileName);
}

そして次に新しいFunctionから呼び出されるライブラリを追加です。

vTigerCRM6の%vtigercrm%/libraries以下を、vTigerCRM5.4の直下へ移動します。
なんとこれだけです。
特に文字化け等の処理を追加する必要もなくこれで上記の問題が解決することができました。

さて、ここまでいくと少し欲が出てて来ます。

文字化けや文字長の問題は解決されましたが、出力されるフォーマットはvTigerCRM6もvTigerCRM5.4も一緒です。

そのフォーマットですが、集計項目に関してはその項目のラベルまでvTigerCRMは出力しれくれません。

使い勝手を考えた場合は当然あるべきな項目となりますので移植したソースをさらに修正します。

そんなわけでまだ「その3」へ続きます。

CRM TOUCHのサイトはこちら
vTigerCRMの日本語の情報に関してはこちら