Blame view

lib/XlsxParser.php 7.76 KB
8e128526   Mihail   add xlsx parser
1
2
3
4
5
6
7
8
  <?php
  /**
   * Created by PhpStorm.
   * User: Tsurkanov
   * Date: 21.10.2015
   * Time: 15:44
   */
  
d0261fd1   Mihail   fixed namespace i...
9
  namespace yii\multiparser;
f6e54131   Mihail   fixed keys and he...
10
  
735c416d   Mihail   add compatibility...
11
  use common\components\CustomVarDamp;
8e128526   Mihail   add xlsx parser
12
  
8e128526   Mihail   add xlsx parser
13
  
8e128526   Mihail   add xlsx parser
14
15
  /**
   * Class XlsxParser
d0261fd1   Mihail   fixed namespace i...
16
   * @package yii\multiparser
8e128526   Mihail   add xlsx parser
17
   */
f6e54131   Mihail   fixed keys and he...
18
19
  class XlsxParser extends TableParser
  {
8e128526   Mihail   add xlsx parser
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  
      /**
       * @var string - путь куда будут распаковываться файлы, если не указанно - во временный каталог сервера
       */
      public $path_for_extract_files = '';
  
  
      /**
       * @var int - если указано то считывание будет производиться с этого листа, иначе со всех листов
       * при чтении со всех листов - выходной массив будет иметь номера листов первыми элементами
       */
      public $active_sheet = 0;
  
      protected $strings_arr = [];
      protected $sheets_arr = [];
  
      protected $current_node;
      protected $current_sheet;
  
2395ca4f   Mihail   add round func fo...
39
      // глубина округления для флоата
ec440fb6   Mihail   add supported ext...
40
      // @todo - перенести в родительский класс и применить в дочерних классах
2395ca4f   Mihail   add round func fo...
41
42
      protected $float_precision = 6;
  
8e128526   Mihail   add xlsx parser
43
44
45
46
47
      public function setup()
      {
  
          parent::setup();
  
f6e54131   Mihail   fixed keys and he...
48
          if ($this->path_for_extract_files == '') {
8e128526   Mihail   add xlsx parser
49
50
51
52
53
54
55
              $this->path_for_extract_files = sys_get_temp_dir();
          }
      }
  
  
      public function read()
      {
f6e54131   Mihail   fixed keys and he...
56
          $this->extractFiles();
8e128526   Mihail   add xlsx parser
57
58
          $this->readSheets();
          $this->readStrings();
f6e54131   Mihail   fixed keys and he...
59
          foreach ($this->sheets_arr as $sheet) {
8e128526   Mihail   add xlsx parser
60
              //проходим по всем файлам из директории /xl/worksheets/
0c6fd004   Mihail   fixed issue with ...
61
              $this->current_sheet = $sheet;
8e128526   Mihail   add xlsx parser
62
              $sheet_path = $this->path_for_extract_files . '/xl/worksheets/' . $sheet . '.xml';
f6e54131   Mihail   fixed keys and he...
63
64
              if (file_exists($sheet_path) && is_readable($sheet_path)) {
                  $xml = simplexml_load_file($sheet_path, "SimpleXMLIterator");
8e128526   Mihail   add xlsx parser
65
66
                  $this->current_node = $xml->sheetData->row;
                  $this->current_node->rewind();
f6e54131   Mihail   fixed keys and he...
67
                  if ($this->current_node->valid()) {
0c6fd004   Mihail   fixed issue with ...
68
                      parent::read();
0c6fd004   Mihail   fixed issue with ...
69
                  }
8e128526   Mihail   add xlsx parser
70
              }
8e128526   Mihail   add xlsx parser
71
          }
0c6fd004   Mihail   fixed issue with ...
72
  
cd8b9f70   Mihail   add cleanUp metho...
73
          $this->cleanUp();
735c416d   Mihail   add compatibility...
74
  
f6e54131   Mihail   fixed keys and he...
75
          if ($this->active_sheet) {
735c416d   Mihail   add compatibility...
76
              // в настройках указан конкретный лист с которого будем производить чтение, поэтому и возвращаем подмассив
f6e54131   Mihail   fixed keys and he...
77
78
              return $this->result[$this->current_sheet];
          } else {
0c6fd004   Mihail   fixed issue with ...
79
80
81
              return $this->result;
          }
  
8e128526   Mihail   add xlsx parser
82
83
      }
  
f6e54131   Mihail   fixed keys and he...
84
      protected function extractFiles()
8e128526   Mihail   add xlsx parser
85
      {
0c6fd004   Mihail   fixed issue with ...
86
          $this->path_for_extract_files = $this->path_for_extract_files . session_id();
f6e54131   Mihail   fixed keys and he...
87
88
89
          if (!file_exists($this->path_for_extract_files)) {
              if (!mkdir($this->path_for_extract_files)) {
                  throw new \Exception('Ошибка создания временного каталога - ' . $this->path_for_extract_files);
0c6fd004   Mihail   fixed issue with ...
90
              }
735c416d   Mihail   add compatibility...
91
          }
0c6fd004   Mihail   fixed issue with ...
92
  
8e128526   Mihail   add xlsx parser
93
          $zip = new \ZipArchive;
f6e54131   Mihail   fixed keys and he...
94
95
          if ($zip->open($this->file_path) === TRUE) {
              $zip->extractTo($this->path_for_extract_files . '/');
8e128526   Mihail   add xlsx parser
96
97
              $zip->close();
          } else {
735c416d   Mihail   add compatibility...
98
  
f6e54131   Mihail   fixed keys and he...
99
              throw new \Exception('Ошибка чтения xlsx файла');
8e128526   Mihail   add xlsx parser
100
          }
221da14e   Mihail   change SplFileObj...
101
          unset($zip);
8e128526   Mihail   add xlsx parser
102
103
      }
  
f6e54131   Mihail   fixed keys and he...
104
      protected function readSheets()
8e128526   Mihail   add xlsx parser
105
      {
f6e54131   Mihail   fixed keys and he...
106
107
          if ($this->active_sheet) {
              $this->sheets_arr[] = 'sheet' . $this->active_sheet;
8e128526   Mihail   add xlsx parser
108
109
110
              return;
          }
  
f6e54131   Mihail   fixed keys and he...
111
112
          $xml = simplexml_load_file($this->path_for_extract_files . '/xl/workbook.xml');
          foreach ($xml->sheets->children() as $sheet) {
8e128526   Mihail   add xlsx parser
113
114
115
              $sheet_name = '';
              $sheet_id = 0;
              $attr = $sheet->attributes();
f6e54131   Mihail   fixed keys and he...
116
              foreach ($attr as $name => $value) {
8e128526   Mihail   add xlsx parser
117
118
119
120
121
122
123
                  if ($name == 'name')
                      $sheet_name = (string)$value;
  
                  if ($name == 'sheetId')
                      $sheet_id = $value;
  
              }
f6e54131   Mihail   fixed keys and he...
124
              if ($sheet_name && $sheet_id) {
8e128526   Mihail   add xlsx parser
125
126
127
128
129
130
                  $this->sheets_arr[$sheet_name] = 'Sheet' . $sheet_id;
              }
  //
          }
      }
  
f6e54131   Mihail   fixed keys and he...
131
      protected function readStrings()
8e128526   Mihail   add xlsx parser
132
      {
b46a9c6c   Mihail   add examples for ...
133
134
135
136
137
138
          $file_with_strings = $this->path_for_extract_files . '/xl/sharedStrings.xml';
          if ( file_exists( $file_with_strings ) ) {
              $xml = simplexml_load_file($file_with_strings);
              foreach ($xml->children() as $item) {
                  $this->strings_arr[] = (string)$item->t;
              }
8e128526   Mihail   add xlsx parser
139
          }
b46a9c6c   Mihail   add examples for ...
140
  
8e128526   Mihail   add xlsx parser
141
142
143
      }
  
  
f6e54131   Mihail   fixed keys and he...
144
      protected function readRow()
8e128526   Mihail   add xlsx parser
145
      {
0c6fd004   Mihail   fixed issue with ...
146
          $this->row = [];
8e128526   Mihail   add xlsx parser
147
          $node = $this->current_node->getChildren();
0c6fd004   Mihail   fixed issue with ...
148
149
150
          if ($node === NULL) {
              return;
          }
f6e54131   Mihail   fixed keys and he...
151
152
  
          for ($node->rewind(), $i = 0; $node->valid(); $node->next(), $i++) {
0c6fd004   Mihail   fixed issue with ...
153
              $child = $node->current();
8e128526   Mihail   add xlsx parser
154
155
              $attr = $child->attributes();
  
f6e54131   Mihail   fixed keys and he...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
              // define the index of result array
              // $attr['r'] - contain the address of cells - A1, B1 ...
              if (isset($attr['r'])) {
                  // override index
                  $i = $this->convertCellToIndex( $attr['r'] );
  
                  if ( $this->keys !== Null ){
                      if( isset( $this->keys[$i] ) ){
                          //$i = $this->keys[$i];
                      } else {
                          // we have a keys, but this one we didn't find, so skip it
                          continue;
                      }
                  }
              }
              // define the value of result array
              if (isset($child->v)) {
8e128526   Mihail   add xlsx parser
173
                  $value = (string)$child->v;
f6e54131   Mihail   fixed keys and he...
174
  
2395ca4f   Mihail   add round func fo...
175
176
                  if ( isset($attr['t']) ){
                      // it's not a value it's a string, so fetch it from string array
b46a9c6c   Mihail   add examples for ...
177
178
179
180
181
182
                      if( empty( $this->strings_arr[$value] ) ){
                          $value = '';
                      } else {
                          $value = $this->strings_arr[$value];
                      }
  
2395ca4f   Mihail   add round func fo...
183
184
185
186
                  } else {
                      $value = (string)round( $value, $this->float_precision );
                  }
  
f6e54131   Mihail   fixed keys and he...
187
              } else {
8e128526   Mihail   add xlsx parser
188
189
                  $value = '';
              }
f6e54131   Mihail   fixed keys and he...
190
191
              // set
              $this->row[$i] = $value;
8e128526   Mihail   add xlsx parser
192
          }
f6e54131   Mihail   fixed keys and he...
193
  
f6e54131   Mihail   fixed keys and he...
194
          ksort( $this->row );
8e128526   Mihail   add xlsx parser
195
          $this->current_node->next();
8e128526   Mihail   add xlsx parser
196
197
      }
  
8e128526   Mihail   add xlsx parser
198
  
f6e54131   Mihail   fixed keys and he...
199
200
      protected function isEmptyColumn($val)
      {
ec440fb6   Mihail   add supported ext...
201
          return $val == '' || $val === null;
8e128526   Mihail   add xlsx parser
202
      }
0c6fd004   Mihail   fixed issue with ...
203
  
f6e54131   Mihail   fixed keys and he...
204
205
206
      protected function setResult()
      {
          $this->result[$this->current_sheet][] = $this->row;
0c6fd004   Mihail   fixed issue with ...
207
208
      }
  
f6e54131   Mihail   fixed keys and he...
209
      protected function deleteExtractFiles()
0c6fd004   Mihail   fixed issue with ...
210
      {
f6e54131   Mihail   fixed keys and he...
211
          $this->removeDir($this->path_for_extract_files);
0c6fd004   Mihail   fixed issue with ...
212
213
214
  
      }
  
f6e54131   Mihail   fixed keys and he...
215
216
      protected function removeDir($dir)
      {
0c6fd004   Mihail   fixed issue with ...
217
218
219
220
          if (is_dir($dir)) {
              $objects = scandir($dir);
              foreach ($objects as $object) {
                  if ($object != "." && $object != "..") {
f6e54131   Mihail   fixed keys and he...
221
222
                      if (filetype($dir . "/" . $object) == "dir")
                          $this->removeDir($dir . "/" . $object);
0c6fd004   Mihail   fixed issue with ...
223
                      else
f6e54131   Mihail   fixed keys and he...
224
                          unlink($dir . "/" . $object);
0c6fd004   Mihail   fixed issue with ...
225
226
227
228
229
230
231
                  }
              }
              reset($objects);
              rmdir($dir);
          }
      }
  
f6e54131   Mihail   fixed keys and he...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
      /**
       * @param $cell_address - string with address like A1, B1 ...
       * @return int - integer index
       * this method has a constraint - 'Z' - it's a last column to convert,
       * column with 'AA..' address and bigger - return index = 0
       */
      protected function convertCellToIndex($cell_address)
      {
          $index = 0;
  
          $address_letter = substr($cell_address, 0, 1);
          $address_arr = range('A', 'Z');
  
          if ( $search_value =  array_search( $address_letter, $address_arr ) )
              $index = $search_value;
  
          return $index;
  
      }
f6e54131   Mihail   fixed keys and he...
251
  
cd8b9f70   Mihail   add cleanUp metho...
252
      protected function cleanUp()
0c6fd004   Mihail   fixed issue with ...
253
      {
cd8b9f70   Mihail   add cleanUp metho...
254
255
256
257
258
          parent::cleanUp();
          unset($this->strings_arr);
          unset($this->sheets_arr);
          unset($this->current_node);
  
cd8b9f70   Mihail   add cleanUp metho...
259
  
0c6fd004   Mihail   fixed issue with ...
260
261
      }
  
f6e54131   Mihail   fixed keys and he...
262
263
264
265
266
      function __destruct()
      {
          $this->deleteExtractFiles();
      }
  
0c6fd004   Mihail   fixed issue with ...
267
  
8e128526   Mihail   add xlsx parser
268
  }