回答編集履歴

1 出力自体は正常である理由の補足

argparse

argparse score 763

2018/12/07 17:57  投稿

単純に、 御使いの PHP 環境で **iconv 拡張が正しく動作していない** ことが原因です。 PhpSpreadsheet 自体には関係無いものと思われます。実際、スクリプトで PhpSpreadsheet の類を一切使用せず、次のようにして**空の文字列を変換させてみるだけでも同じエラーメッセージが出力され** ませんでしょうか。
```php
<?php
iconv('UTF-8', 'UTF-16LE//IGNORE//TRANSLIT', '');
```
メッセージ曰く、どう考えても適切であるはずの "UTF-8" や "UTF-16" を **「誤った文字コード (Wrong charset)」** であると主張しているので、恐らくは何らかの原因で iconv の環境が破損しており、当該文字コードに対応する gconv モジュールの読み込みに失敗しているのではないでしょうか。
対策としては、使っている **OS 環境や `php -i` 情報等を見直しながら iconv 拡張を正しく動作するように修正する** ことになると思います。
あるいは、問題の個所である `StringHelper::convertEncoding()` では [iconv が無効であれば mbstring を使う](https://github.com/PHPOffice/PhpSpreadsheet/blob/501f5722be780cd60a43e7c041af40b3602324f0/src/PhpSpreadsheet/Shared/StringHelper.php#L444-L463) 実装となって居りますから、 (もし可能であれば) **iconv 拡張を無効化してしまい、代わりに mbstring 拡張を使わせる** という方法もあるかもしれません。何れにせよ、実行環境の精査や再構築が必要とみられます。
あるいは、問題の個所である `StringHelper::convertEncoding()` では [iconv が無効であれば mbstring を使う](https://github.com/PHPOffice/PhpSpreadsheet/blob/501f5722be780cd60a43e7c041af40b3602324f0/src/PhpSpreadsheet/Shared/StringHelper.php#L444-L463) 実装となって居ります (一応正常に保存できているのはこの実装のおかげ) から、 (もし可能であれば) **iconv 拡張を無効化してしまい、代わりに mbstring 拡張を使わせる** という方法もあるかもしれません。何れにせよ、実行環境の精査や再構築が必要とみられます。
# おまけ: なぜ、空のファイルの保存でも文字コード変換エラーが出力されるのか?
仮にシート内が空のファイルであっても、「シート名 (PhpSpreadsheet ではデフォルトで "Worksheet")」であるとか、「フォント名」であるとか、 **何かしらファイルに保存しなければならない文字列が存在する** からです。
今回のエラーは、「変換しようとした文字列が、 **変換できないものであった**」というエラーではなく、「変換機能そのものが死んでいて、変換を **試みる事すらできなかった**」というエラーであることに注意してください。そのため、何かしらファイルに保存すべき文字列があって、かつそれが文字コードの変換を必要とする限り、元が日本語だろうが英語だろうが空文字列だろうが関係なくエラーが出力される事になります。
# おまけ 2: なぜ、 `*.xlsx` だと大丈夫なのか?
ファイルに含める文字列の文字コードを変換する必要が無いからです。
前提として PhpSpreadsheet では [FAQ にも記載されている](https://phpspreadsheet.readthedocs.io/en/develop/faq/#there-seems-to-be-a-problem-with-character-encoding) 通り、インターフェース上 **全ての文字列は UTF-8 で読み書きする仕様** となっております。
そして、 `*.xlsx` 形式は [Office Open XML](https://ja.wikipedia.org/wiki/Office_Open_XML) と呼ばれる、 (雑に言えば) **XML ファイルの集合を Zip アーカイブにまとめた形式** のファイルです。従って、 `*.xlsx` ファイルを出力する場合は **UTF-8 で書かれた XML ファイルを出力すればよい** (ファイル先頭の XML 宣言で `encoding="UTF-8"` とすればよい) ため、特に文字コードを変換する必要が生じません。
一方、 `*.xls` 形式、より正確には BIFF8 と呼ばれる Excel 97-2003 形式では、文字列は **常に UTF-16LE で保存する仕様になって** います。この事実は、あまり適切なソースが見当たらないのですが、例えば [PhpSpreadsheet\\Reader\\Xls クラスのソース](https://github.com/PHPOffice/PhpSpreadsheet/blob/501f5722be780cd60a43e7c041af40b3602324f0/src/PhpSpreadsheet/Reader/Xls.php#L209-L215) にも次のようなコメントが御座いますし、他にも非公式な情報源であれば検索すると見当たると思います。
> For BIFF8 (Excel 97 - Excel 2003) this will always have the value 'UTF-16LE'.
いずれにせよ、 `*.xls` 形式は **読み書きの際に必ず文字コードの変換を行わなければならない** ことが分かります。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る