回答編集履歴

2

追加調査

2020/07/11 00:29

投稿

makotokw
makotokw

スコア24

test CHANGED
@@ -221,3 +221,91 @@
221
221
  }
222
222
 
223
223
  ```
224
+
225
+
226
+
227
+ **【根本的な原因】**
228
+
229
+ phpspreadsheetの内部で使用している、`zipstream-php`というライブラリにバグがある。
230
+
231
+ https://github.com/maennchen/ZipStream-PHP/issues/154
232
+
233
+  
234
+
235
+ xlsxファイルを解凍後に再圧縮するのではなく、phpspreadsheetを暫定修正する方法も考えてみた。
236
+
237
+  
238
+
239
+ **【phpspreadsheetを暫定的に修正】**
240
+
241
+ 既にZipファイルに追加されているファイルは複数回追加されないようにチェック。
242
+
243
+ `vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Writer\Xlsx.php`
244
+
245
+ ```php
246
+
247
+
248
+
249
+ public function save($pFilename)
250
+
251
+      :
252
+
253
+      :
254
+
255
+
256
+
257
+ 《280行目付近》
258
+
259
+
260
+
261
+ // Add worksheet relationships (drawings, ...)
262
+
263
+ $added_files = array(); // ※追加
264
+
265
+ for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
266
+
267
+ // Add relationships
268
+
269
+ $zip->addFile('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts));
270
+
271
+
272
+
273
+ // Add unparsedLoadedData
274
+
275
+ $sheetCodeName = $this->spreadSheet->getSheet($i)->getCodeName();
276
+
277
+ $unparsedLoadedData = $this->spreadSheet->getUnparsedLoadedData();
278
+
279
+ if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'])) {
280
+
281
+ foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'] as $ctrlProp) {
282
+
283
+ $zip->addFile($ctrlProp['filePath'], $ctrlProp['content']);
284
+
285
+ }
286
+
287
+ }
288
+
289
+ if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'])) {
290
+
291
+ foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'] as $ctrlProp) {
292
+
293
+ if(!isset($added_files[$ctrlProp['filePath']])) { // ※追加
294
+
295
+ $zip->addFile($ctrlProp['filePath'], $ctrlProp['content']);
296
+
297
+ $added_files[$ctrlProp['filePath']] = $ctrlProp['filePath']; // ※追加
298
+
299
+ } // ※追加
300
+
301
+ }
302
+
303
+ }
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+ ```

1

追加調査結果繁栄

2020/07/11 00:29

投稿

makotokw
makotokw

スコア24

test CHANGED
@@ -1,17 +1,47 @@
1
- 根本的原因はわからないのですが、なんとなく状況がわかってきました。
1
+ 詳細な状況がわかってきました。
2
-
3
-
4
-
2
+
5
- Excel2019で保存したExcelファイルをテンプレートとし使用すとダメ見たいです。
3
+ テンプレートとなるExcelファイルのシートにプリンタ設定情報が含ま場合、
4
+
6
-
5
+ そのシートをコピーすると、コピーされた新しいシートにも同じプリンタ設定情報がコピーされます。
6
+
7
+
8
+
7
-
9
+ phpspreadsheetで、コピーしたシートのプリンタ設定情報の扱いがバグっている感じです。
10
+
8
-
11
+ ![イメージ説明](20e75c429737802da14f952e9f30257c.jpeg)
12
+
13
+
14
+
9
-
15
+ 【確認方法】
16
+
17
+ 1.生成後エラーが出るxlsxファイルの拡張子をzipに変更。
18
+
19
+ 2.エクスプローラーでzipファイルをダブルクリック。
20
+
21
+ 3.フォルダ移動。 xl\printerSettings\
22
+
23
+ ※ここのフォルダに同じ名前の printerSettings1.bin がコピーしたシート数分あります。
24
+
25
+  
26
+
27
+  
28
+
29
+ **phpspreadsheet自体を修正する技術量はないので、暫定対応で回避する。**
30
+
31
+
32
+
33
+ 【暫定対応】
34
+
35
+ 1.phpspreadsheetで生成されたxlsxファイルをunzipで解凍し、重複ファイルを1つにする。
36
+
37
+ 2.解凍されたファイルをzipで再圧縮する。 ※拡張子は .xlsx で圧縮
38
+
39
+
40
+
41
+
10
42
 
11
43
  ```php
12
44
 
13
- <?php
14
-
15
45
  require '../phpLibs/PhpSpreadsheet/vendor/autoload.php';
16
46
 
17
47
 
@@ -28,19 +58,13 @@
28
58
 
29
59
  // Excel2016の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート
30
60
 
31
- // 【生成ファイル】 OK !!
32
-
33
61
  copyTemplateSheet('../tmp/Excel2016_Rclick_NEW.xlsx',
34
62
 
35
63
  '../tmp/Excel2016_Rclick_NEW_generate.xlsx');
36
64
 
37
65
 
38
66
 
39
- // Excel2016の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート
67
+ // Excel2016の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート ※新規作成後、ファイルを開いて内容を更新して保存
40
-
41
- // ※新規作成後、ファイルを開いて内容を更新して保存
42
-
43
- // 【生成ファイル】 OK !!
44
68
 
45
69
  copyTemplateSheet('../tmp/Excel2016_Rclick_NEW_Save.xlsx',
46
70
 
@@ -48,21 +72,23 @@
48
72
 
49
73
 
50
74
 
75
+ // Excel2016の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート ※新規作成後、ファイルを開いて内容を更新して保存(プリンタ設定を変更)
76
+
77
+ copyTemplateSheet('../tmp/Excel2016_Rclick_NEW_Save2.xlsx',
78
+
79
+ '../tmp/Excel2016_Rclick_NEW_Save2_generate.xlsx');
80
+
81
+
82
+
51
83
  // Excel2019の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート
52
84
 
53
- // 【生成ファイル】 OK !!
54
-
55
85
  copyTemplateSheet('../tmp/Excel2019_Rclick_NEW.xlsx',
56
86
 
57
87
  '../tmp/Excel2019_Rclick_NEW_generate.xlsx');
58
88
 
59
89
 
60
90
 
61
- // Excel2019の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート
91
+ // Excel2019の環境で、右クリック⇒新規作成⇒Microsoft Excel ワークシート ※新規作成後、ファイルを開いて内容を更新して保存
62
-
63
- // ※新規作成後、ファイルを開いて内容を更新して保存
64
-
65
- // 【生成ファイル】 NG !!!!
66
92
 
67
93
  copyTemplateSheet('../tmp/Excel2019_Rclick_NEW_Save.xlsx',
68
94
 
@@ -76,6 +102,12 @@
76
102
 
77
103
  function copyTemplateSheet($load_filename, $save_filename) {
78
104
 
105
+ $save_folder = realpath(pathinfo($save_filename, PATHINFO_DIRNAME));
106
+
107
+ $save_basename = pathinfo($save_filename, PATHINFO_BASENAME );
108
+
109
+
110
+
79
111
  try {
80
112
 
81
113
  $reader = new XlsxReader();
@@ -104,6 +136,52 @@
104
136
 
105
137
  $writer->save($save_filename);
106
138
 
139
+
140
+
141
+ // 解凍先のtmpフォルダ作成
142
+
143
+ if(file_exists($save_filename.'.tmp')) {
144
+
145
+ removeDirectory($save_filename.'.tmp');
146
+
147
+ }
148
+
149
+ mkdir($save_filename.'.tmp', 0777, true);
150
+
151
+
152
+
153
+ //tmpフォルダにxlsxファイルを解凍 ※xlsxファイルはzip圧縮されている?
154
+
155
+ //この段階で、重複しているファイルが1つにまとめられる
156
+
157
+ shell_exec('unzip -o '.$save_filename.' -d '.$save_filename.'.tmp');
158
+
159
+
160
+
161
+ // 生成されたxlsxファイルを削除
162
+
163
+ unlink($save_filename);
164
+
165
+
166
+
167
+ // tmpフォルダの内容で再圧縮し、xlsxファイルを作成する
168
+
169
+ $cwd = getcwd();
170
+
171
+ chdir($save_filename.'.tmp');
172
+
173
+ shell_exec('zip -r '.$save_folder.'/'.$save_basename.' *');
174
+
175
+ chdir($cwd);
176
+
177
+
178
+
179
+ // tmpフォルダを削除
180
+
181
+ removeDirectory($save_filename.'.tmp');
182
+
183
+
184
+
107
185
  } catch(Exception $e) {
108
186
 
109
187
  die('Error: '.$e->getMessage());
@@ -112,8 +190,34 @@
112
190
 
113
191
  }
114
192
 
193
+
194
+
195
+ function removeDirectory($directory) {
196
+
197
+ $result = true;
198
+
199
+ foreach(new \RecursiveIteratorIterator(
200
+
201
+ new \RecursiveDirectoryIterator($directory, \RecursiveDirectoryIterator::SKIP_DOTS),
202
+
203
+ \RecursiveIteratorIterator::CHILD_FIRST
204
+
205
+ ) as $file) {
206
+
207
+ if ($file->isDir()) {
208
+
209
+ $result &= @rmdir($file->getPathname());
210
+
211
+ } else {
212
+
213
+ $result &= @unlink($file->getPathname());
214
+
215
+ }
216
+
217
+ }
218
+
219
+ return $result && @rmdir($directory);
220
+
221
+ }
222
+
115
223
  ```
116
-
117
-
118
-
119
- ご回答くださった方々、ありがとうございました♪