【问题标题】:Convert spreadsheet with varying col/rowspans to HTML table将具有不同 col/rowspans 的电子表格转换为 HTML 表格
【发布时间】:2020-11-07 00:26:01
【问题描述】:

背景: 我们的客户将他们的费率保存在 xlsx 电子表格中,并希望能够将其上传到他们的网站并自动填充 HTML 表格。电子表格中的一些单元格覆盖多行,一些单元格覆盖多列,以填充任何空白,例如:

 _______________________
|___|___|___|___|___|   |
|   |   |___|___|___|___|
|   |   |___|___|___|___|
|   |   |___|___|_______|
|___|___|___|___|_______|
|___________________|___|

(可能无法仅通过确定哪些单元格为空来确定列或行的跨度,即使一个单元格位于一个空单元格的顶部,也不能假设它会跨越自身并且下面的单元格,因为空单元格左侧的单元格可能跨越 2 列。)

另一个复杂因素是费率一直在变化,并且不能相信客户会坚持使用预先制作的电子表格模板。 (我注意到在我用作参考的电子表格中,他们正确设置了边框,但没有在同一边框内合并单元格。)

有没有人遇到过这个问题并想出了如何解决它?

谢谢!

吉尔

【问题讨论】:

    标签: parsing spreadsheet


    【解决方案1】:

    好的,我会回答我自己的问题。我发现如何做到这一点的方法是使用PHPSpreadsheet getMergeCells() 函数。它不是很高效或漂亮,但它确实如此......

    以下代码执行以下操作:

    1. 首先,我使用 getMergeCells() 从 xlsx 文件中收集所有合并的单元格,并存储为字符串数组,类似于 ["A1:F1", "H6:H7"]
    2. 对于每个单元格,我检查它是否是合并的单元格之一
    3. 如果是,我通过用冒号字符拆分合并的单元格字符串并保留第二个元素来获得结束单元格
    4. 然后,我确定步骤 3 中合并的单元格字符串结束坐标与当前单元格坐标之间的哪个坐标不同。如果它是第一个坐标,我会增加行跨度。如果是第二个,我会增加 colspan。
    5. 我使用了一个 for 循环,它从当前单元格的 x 或 y 坐标开始,并增加直到它与合并的单元格字符串结束坐标匹配,增加一个稍后在输出将代表该单元格的表格单元格时使用的变量电子表格

    这段代码是用 Blade 编写的,它看起来很像 PHP,减去带有额外 '@' 的花括号......我认为它更具可读性。请注意,“$file”变量是在不同的文件中定义的。我不使用 PHPSpreadsheet 的 getHighestColumn() 函数,因为这个特定的电子表格在它的右侧有很多东西,但该函数可供任何需要它的人使用。

    ...
      
    
     @php
          $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
          $reader->setReadEmptyCells(false);
    
          $spreadsheet = $reader->load($file);
          $table = $spreadsheet->getActiveSheet();
          
          $highestRow = $table->getHighestDataRow(); // e.g. 10
          $columns = ['A', 'B', 'C', 'D', 'E', 'F'];
          $last_col = $columns[sizeof($columns) - 1];
    
          $highestColumn = sizeof($columns);
          // **Step 1**
          $mergeCells = $table->getMergeCells();
    
    
      @endphp
    
      <table>
        @for ($row = 4; $row <= $highestRow; $row++)
          <tr>
            @foreach ($columns as $index => $letter_coordinate)
    
              @php $colspan   = 1;
                   $rowspan   = 1;
                   $cell      = $table->getCell($letter_coordinate . $row);
                   $data      = $cell->getValue();
                   // check is data is excel function (or a numerical value)
                   if (substr($data, 0, 1) == '=' || is_numeric($data)) {
                    $data = number_format((float)$cell->getCalculatedValue() * 100, 2, '.', '') . '%';
                   }
              @endphp
              {{-- **Step 2**: Check if cell is merged --}}
              @foreach ($mergeCells as $cells)
                @if ($cell->isInRange($cells))
                  {{-- **Step 3** --}}
                  @php $limit = explode(":", $cells)[1] @endphp
                  {{-- **Step 4** --}}
                  @if ($limit[0] != $letter_coordinate) {{-- if letter letter_coordinate doesn't match --}}
                    {{-- **Step 5** --}}
                    @for ($i = $letter_coordinate; $i != $last_col; $i++)
                      @if ($limit == $i . $row )
                        @break
                      @else
                        @php $colspan++ @endphp
                      @endif
                    @endfor
                  @else
                    {{-- Step 5 (alternative)--}}
                    {{-- Find row span --}}
                    @for ($i = $row; $i <= $highestRow; $i++)
                      @if ($limit == $letter_coordinate . $i)
                        @break
                      @else
                        @php $rowspan++ @endphp
                      @endif
                    @endfor
                  @endif
                @endif
              @endforeach
              
              {{-- break to new table if all cells are empty --}}
              @if ($colspan == $highestColumn and $cell == "" and $table_row > 5)
                  </tr>
                </table>
                 <table>
    
              @else {{-- if row has one or more cells --}}
                @unless ($cell == "")
                 
                  <td
                    colspan="{{ $colspan }}" 
                    rowspan="{{ $rowspan }}"
                  >{{ $data }}
                  </td>
                @endunless
              @endif
            @endforeach
          </tr>
        @endfor
      </table>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-21
      • 2019-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-05-27
      • 2020-07-19
      相关资源
      最近更新 更多