Как сделать столбцы Excel доступными только для чтения через XLSXWriter или подкласс?Php

Кемеровские программисты php общаются здесь
Ответить
Anonymous
 Как сделать столбцы Excel доступными только для чтения через XLSXWriter или подкласс?

Сообщение Anonymous »

Итак, мы работаем с PHP-проектом, используем Yii, но для вопроса это не очень важно. Для экспорта мы используем XLSXWriter (см. https://github.com/mk-j/PHP_XLSXWriter/ ... .class.php). Это не новая библиотека, и она не поддерживается очень часто, однако последние запросы на экспорт Excel включали:
  • поддержку скрытия полей
  • поддержку полей только для чтения
Они не поддерживаются XLSXWriter «из коробки», поэтому мы рассматриваем возможность перехода на PHPSpreadsheet в качестве альтернативы, но даже если мы это сделаем, мы бы предпочли сначала иметь быстрое решение с использованием XLSXWriter, чтобы избежать сравнительного анализа и тестирования всего экспорта и уложиться в сроки. Поэтому я искал способы заставить запросы работать с тем, что у нас есть на данный момент, и увидел это
  • Код: Выделить всё

    initializeSheet
    жестко закодирует скрытый="false" в тег col согласно $sheet->file_writer->write( '');
  • Код: Выделить всё

    writeSheetRow
    не передает ему ширину столбца, как указано в $this->initializeSheet($sheet_name);
Поэтому, чтобы это работало, я реализовал подкласс, который решает проблему сокрытия полей, если вы передаете для них ширину столбца 0:

Код: Выделить всё

 $number_format,//contains excel format like 'YYYY-MM-DD HH:MM:SS'
'number_format_type' => $number_format_type, //contains friendly format like 'datetime'
'default_cell_style' => $cell_style_idx,
);
}
return $column_types;
}

private static function numberFormatStandardized($num_format)
{
if ($num_format=='money') { $num_format='dollar'; }
if ($num_format=='number') { $num_format='integer'; }

if      ($num_format=='string')   $num_format='@';
else if ($num_format=='integer')  $num_format='0';
else if ($num_format=='date')     $num_format='YYYY-MM-DD';
else if ($num_format=='datetime') $num_format='YYYY-MM-DD HH:MM:SS';
else if ($num_format=='time')     $num_format='HH:MM:SS';
else if ($num_format=='price')    $num_format='#,##0.00';
else if ($num_format=='dollar')   $num_format='[$$-1009]#,##0.00;[RED]-[$$-1009]#,##0.00';
else if ($num_format=='euro')     $num_format='#,##0.00 [$€-407];[RED]-#,##0.00 [$€-407]';
$ignore_until='';
$escaped = '';
for($i=0,$ix=strlen($num_format); $inumber_formats, $number_format);
$lookup_string = $number_format_idx.";".$cell_style_string;
$cell_style_idx = self::add_to_list_get_index($this->cell_styles, $lookup_string);
return $cell_style_idx;
}
}
Это успешно скрывает столбцы, которые я хотел скрыть, но я не знаю, как сделать ячейки или столбцы доступными только для чтения. В writeStylesXML я заметил часть

Код: Выделить всё

$file->write('  
');
но я не уверен, как его использовать и делает ли он вообще столбец/ячейку доступным только для чтения. Есть ли способ сделать столбец или ячейку доступной только для чтения с помощью XLSXWriter или подкласса? У меня уже есть подкласс, переопределяющий некоторые части, которые не поддерживаются реальным классом, поэтому я открыт для любых предложений.
РЕДАКТИРОВАТЬ
Согласно ответу Оливье, я исправил FinalizeSheet согласно

Код: Выделить всё

    protected function finalizeSheet($sheet_name)
{
if (empty($sheet_name) || $this->sheets[$sheet_name]->finalized)
return;

$sheet = &$this->sheets[$sheet_name];

$sheet->file_writer->write(    '');

$sheet->file_writer->write(    '');

if (!empty($sheet->merge_cells)) {
$sheet->file_writer->write(    '');
foreach ($sheet->merge_cells as $range) {
$sheet->file_writer->write(        '');
}
$sheet->file_writer->write(    '');
}

$max_cell = self::xlsCell($sheet->row_count - 1, count($sheet->columns) - 1);

if ($sheet->auto_filter) {
$sheet->file_writer->write(    '');
}

$sheet->file_writer->write(    '
');
$sheet->file_writer->write(    '');
$sheet->file_writer->write(    '');
$sheet->file_writer->write(    '');
$sheet->file_writer->write(        '&C&"Times New Roman,Regular"&12&A');
$sheet->file_writer->write(        '&C&"Times New Roman,Regular"&12Page &P');
$sheet->file_writer->write(    '');
$sheet->file_writer->write('');

$max_cell_tag = '';
$padding_length = $sheet->max_cell_tag_end - $sheet->max_cell_tag_start - strlen($max_cell_tag);
$sheet->file_writer->fseek($sheet->max_cell_tag_start);
$sheet->file_writer->write($max_cell_tag.str_repeat(" ", $padding_length));
$sheet->file_writer->close();
$sheet->finalized=true;
}
Но я не знаю, как можно заблокировать отдельные столбцы. Пробовал сделать

Код: Выделить всё

$value = '
' . $value;
внутри writeCell, чтобы узнать, заблокирует ли это ячейку. Но это добавило его в стоимость. Возможно, я упускаю что-то очевидное.
EDIT2

Код: Выделить всё

finalizeSheet
не вызывается автоматически, и, поскольку он защищен, для его вызова я переопределил в подклассе, как указано Оливье в его ответе, а также вспомогательную функцию, а именно

Код: Выделить всё

    public function finalize($sheet_name)
{
$this->finalizeSheet($sheet_name);
}
И я вызываю его в конце экспорта, после написания строк, например

Код: Выделить всё

        $this->excelWriter->finalize();
$this->excelWriter->close();
где excelWriter — это экземпляр другого класса, функции которого здесь вызываются

Код: Выделить всё

    public function finalize()
{
$this->workbook->finalize($this->currentSheet);
}

public function close()
{
$this->workbook->writeToFile($this->filename);
if ($this->forceDownload) {
header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
header("Content-Disposition: attachment; filename=\"{$this->webfilename}.xlsx\"");
header('Content-Length: ' . filesize($this->filename));
readfile($this->filename);
}
return $this->workbook;
}
и теперь он успешно вызван, и, как утверждал Оливье (правильно), он делает все доступным только для чтения. Поэтому мне нужно будет разблокировать ячейки, которые должны быть доступны для редактирования. Однако я не знаю, как это сделать.

Подробнее здесь: https://stackoverflow.com/questions/798 ... a-subclass
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Php»