シフトJISのCSVを読込みテンプレートのExcelに書き込む ~ PHP

2018年8月3日

現在でも使用しているシステムの関係でシフトJISを使用していることがあると思いますが、PHPの文字コードはUnicode(UTF-8)であるため、漢字やひらがなの全角文字を読み込むと表示されない場合があります。

今回はfgetcsvとphpspreadsheetを用いたcsv読込を説明します。

あ,い,う
a2,b2,c2
a3,b3,c3

のようなCSVデータと何も入れていないxlsxファイルを用意してください。

 

fgetcsv

全角文字をそのまま読み込むと「FALSE」で表示されてしまいました。これを回避するため、setlocaleとmb_convert_variablesを使います。

<?php
require "d:/oss/php/php726/vendor/autoload.php";

use PhpOffice\PhpSpreadsheet\Settings;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheet\Writer\CSV as CSVWriter;

// Excel読込
$reader = new XlsxReader();
$spreadsheet = $reader->load('test.xlsx');

// ロケール設定
setlocale(LC_ALL, 'ja_JP.UTF-8');
// CSV読み込み
$line = 0;
$fp = fopen( 'test.csv', 'r' );
while( $dataRow = fgetcsv( $tmp ) ) {
  $line++;
  for($i = 0; $i < count( $dataRow ); ++$i ){
mb_convert_variables($dataRow, "UTF-8","SJIS-win");
//列、行指定
    $spreadsheet->getActiveSheet()->setCellValueByColumnAndRow( $i + 1, $line, $dataRow[$i] );
  }
}
fclose( $tmp );

   
// Excel出力
$writer = new XlsxWriter($spreadsheet);
$writer->save('test1.xlsx');

Window7ではこれで日本語が表示されたのですが、Windows10ではA1の日本語のセルが「あ」ですがB1のセルは「縺」になってしまいました。2列目移行がうまく変換されないようです。

シフトJISのファイルをfgetcsvで読み込むと文字化けしてしまう場合は、一旦UTF-8の文字コードのファイルに文字コードを変換して出力してからfgetcsvで読み込みこむ方法があります。

<?php
require "d:/oss/php/php726/vendor/autoload.php";

use PhpOffice\PhpSpreadsheet\Settings;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheet\Writer\CSV as CSVWriter;

// Excel読込
$reader = new XlsxReader();
$spreadsheet = $reader->load('test.xlsx');

// ロケール設定
setlocale(LC_ALL, 'ja_JP.UTF-8');

// 文字コード変換とtmpファイル書き込み
$fdata = file_get_contents('test.csv');
$fdata = mb_convert_encoding($fdata, 'UTF-8', 'SJIS-win');
$tmp = tmpfile();
fwrite($tmp, $fdata);
rewind($tmp);
// CSV読み込み
$line = 0;
while( $dataRow = fgetcsv( $tmp ) ) {
  $line++;
  for($i = 0; $i < count( $dataRow ); ++$i ){
//列、行指定
    $spreadsheet->getActiveSheet()->setCellValueByColumnAndRow( $i + 1, $line, $dataRow[$i] );
  }
}
fclose( $tmp );

   
// Excel出力
$writer = new XlsxWriter($spreadsheet);
$writer->save('test2.xlsx');

phpspreadsheet

phpspreadsheetでもcsvを読み込めます。

 

<?php
require "d:/oss/php/php726/vendor/autoload.php";

use PhpOffice\PhpSpreadsheet\Settings;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx as XlsxWriter;
use PhpOffice\PhpSpreadsheet\Reader\CSV as CSVReader;

// Excel読込
$reader = new XlsxReader();
$spreadsheet = $reader->load('test1.xlsx');

// CSV読込
$reader2 = new CSVReader();
$reader2->setInputEncoding('SJIS');
$spreadsheetcsv = $reader2->load('test2.csv');
$arrayData = $spreadsheetcsv->getActiveSheet()->toArray();
$spreadsheet->getActiveSheet()->fromArray($arrayData,NULL,'A1');
   
// Excel出力
$writer = new XlsxWriter($spreadsheet);
$writer->save('test3.xlsx');

setInputEncodeingをしないで実行すると、全角文字のセルは書き込まれませんので、日本語を使う場合はいれておいてください。

PHP Fatal error: Uncaught Error: Call to undefined function PhpOffice\PhpSpreadsheet\Reader\mime_content_type() in D:\oss\PHP\PHP726\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Reader\Csv.php:510

しかし、エラーがでてしまいます。

エラーのファイルと行数が出ているのでcsv.phpのソースファイルを変更します。

public function canRead($pFilename)
{
// Check if file exists
try {
$this->openFile($pFilename);
} catch (Exception $e) {
return false;
}fclose($this->fileHandle);$type = mime_content_type($pFilename);
$supportedTypes = [
'text/csv’,
'text/plain’,
'inode/x-empty’,
];return in_array($type, $supportedTypes, true);
}
public function canRead($pFilename)
{
// Check if file exists
try {
$this->openFile($pFilename);
} catch (Exception $e) {
return false;
}fclose($this->fileHandle);// $type = mime_content_type($pFilename);
// $supportedTypes = [
// 'text/csv’,
// 'text/plain’,
// 'inode/x-empty’,
// ];// return in_array($type, $supportedTypes, true);
return True;
}

これで簡単にexcelテンプレートにcsvのデータを入れることができます。

 

PHP

Posted by eightban