/** * Insert a new column, updating all possible related data * * @param int $pBefore Insert before this one * @param int $pNumCols Number of columns to insert * @param int $pNumRows Number of rows to insert * @throws Exception */ public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = null) { // Get a copy of the cell collection /*$aTemp = $pSheet->getCellCollection(); $aCellCollection = array(); foreach ($aTemp as $key => $value) { $aCellCollection[$key] = clone $value; }*/ $aCellCollection = $pSheet->getCellCollection(); // Get coordinates of $pBefore $beforeColumn = 'A'; $beforeRow = 1; list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); // Clear cells if we are removing columns or rows $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); // 1. Clear column strips if we are removing columns if ($pNumCols < 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols > 0) { for ($i = 1; $i <= $highestRow - 1; ++$i) { for ($j = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1 + $pNumCols; $j <= PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2; ++$j) { $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; $pSheet->removeConditionalStyles($coordinate); if ($pSheet->cellExists($coordinate)) { $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); $pSheet->getCell($coordinate)->setXfIndex(0); } } } } // 2. Clear row strips if we are removing rows if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { for ($i = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; $pSheet->removeConditionalStyles($coordinate); if ($pSheet->cellExists($coordinate)) { $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); $pSheet->getCell($coordinate)->setXfIndex(0); } } } } // Loop through cells, bottom-up, and change cell coordinates while ($cell = $pNumCols < 0 || $pNumRows < 0 ? array_shift($aCellCollection) : array_pop($aCellCollection)) { // New coordinates $newCoordinates = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($cell->getColumn()) - 1 + $pNumCols) . ($cell->getRow() + $pNumRows); // Should the cell be updated? Move value and cellXf index from one cell to another. if (PHPExcel_Cell::columnIndexFromString($cell->getColumn()) >= PHPExcel_Cell::columnIndexFromString($beforeColumn) && $cell->getRow() >= $beforeRow) { // Update cell styles $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); $cell->setXfIndex(0); // Insert this cell at its new location if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { // Formula should be adjusted $pSheet->setCellValue($newCoordinates, $this->updateFormulaReferences($cell->getValue(), $pBefore, $pNumCols, $pNumRows)); } else { // Formula should not be adjusted $pSheet->setCellValue($newCoordinates, $cell->getValue()); } // Clear the original cell $pSheet->setCellValue($cell->getCoordinate(), ''); } } // Duplicate styles for the newly inserted cells $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); if ($pNumCols > 0 && PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 > 0) { for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { // Style $coordinate = PHPExcel_Cell::stringFromColumnIndex(PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2) . $i; if ($pSheet->cellExists($coordinate)) { $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? $pSheet->getConditionalStyles($coordinate) : false; for ($j = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $j <= PHPExcel_Cell::columnIndexFromString($beforeColumn) - 2 + $pNumCols; ++$j) { $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); if ($conditionalStyles) { $cloned = array(); foreach ($conditionalStyles as $conditionalStyle) { $cloned[] = clone $conditionalStyle; } $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned); } } } } } if ($pNumRows > 0 && $beforeRow - 1 > 0) { for ($i = PHPExcel_Cell::columnIndexFromString($beforeColumn) - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { // Style $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); if ($pSheet->cellExists($coordinate)) { $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? $pSheet->getConditionalStyles($coordinate) : false; for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) { $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex); if ($conditionalStyles) { $cloned = array(); foreach ($conditionalStyles as $conditionalStyle) { $cloned[] = clone $conditionalStyle; } $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned); } } } } } // Update worksheet: column dimensions $aColumnDimensions = array_reverse($pSheet->getColumnDimensions(), true); if (count($aColumnDimensions) > 0) { foreach ($aColumnDimensions as $objColumnDimension) { $newReference = $this->updateCellReference($objColumnDimension->getColumnIndex() . '1', $pBefore, $pNumCols, $pNumRows); list($newReference) = PHPExcel_Cell::coordinateFromString($newReference); if ($objColumnDimension->getColumnIndex() != $newReference) { $objColumnDimension->setColumnIndex($newReference); } } $pSheet->refreshColumnDimensions(); } // Update worksheet: row dimensions $aRowDimensions = array_reverse($pSheet->getRowDimensions(), true); if (count($aRowDimensions) > 0) { foreach ($aRowDimensions as $objRowDimension) { $newReference = $this->updateCellReference('A' . $objRowDimension->getRowIndex(), $pBefore, $pNumCols, $pNumRows); list(, $newReference) = PHPExcel_Cell::coordinateFromString($newReference); if ($objRowDimension->getRowIndex() != $newReference) { $objRowDimension->setRowIndex($newReference); } } $pSheet->refreshRowDimensions(); $copyDimension = $pSheet->getRowDimension($beforeRow - 1); for ($i = $beforeRow; $i <= $beforeRow - 1 + $pNumRows; ++$i) { $newDimension = $pSheet->getRowDimension($i); $newDimension->setRowHeight($copyDimension->getRowHeight()); $newDimension->setVisible($copyDimension->getVisible()); $newDimension->setOutlineLevel($copyDimension->getOutlineLevel()); $newDimension->setCollapsed($copyDimension->getCollapsed()); } } // Update worksheet: breaks $aBreaks = array_reverse($pSheet->getBreaks(), true); foreach ($aBreaks as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { $pSheet->setBreak($newReference, $value); $pSheet->setBreak($key, PHPExcel_Worksheet::BREAK_NONE); } } // Update worksheet: hyperlinks $aHyperlinkCollection = array_reverse($pSheet->getHyperlinkCollection(), true); foreach ($aHyperlinkCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { $pSheet->setHyperlink($newReference, $value); $pSheet->setHyperlink($key, null); } } // Update worksheet: data validations $aDataValidationCollection = array_reverse($pSheet->getDataValidationCollection(), true); foreach ($aDataValidationCollection as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { $pSheet->setDataValidation($newReference, $value); $pSheet->setDataValidation($key, null); } } // Update worksheet: merge cells $aMergeCells = $pSheet->getMergeCells(); $aNewMergeCells = array(); // the new array of all merge cells foreach ($aMergeCells as $key => &$value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); $aNewMergeCells[$newReference] = $newReference; } $pSheet->setMergeCells($aNewMergeCells); // replace the merge cells array // Update worksheet: protected cells $aProtectedCells = array_reverse($pSheet->getProtectedCells(), true); foreach ($aProtectedCells as $key => $value) { $newReference = $this->updateCellReference($key, $pBefore, $pNumCols, $pNumRows); if ($key != $newReference) { $pSheet->protectCells($newReference, $value, true); $pSheet->unprotectCells($key); } } // Update worksheet: autofilter if ($pSheet->getAutoFilter() != '') { $pSheet->setAutoFilter($this->updateCellReference($pSheet->getAutoFilter(), $pBefore, $pNumCols, $pNumRows)); } // Update worksheet: freeze pane if ($pSheet->getFreezePane() != '') { $pSheet->freezePane($this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows)); } // Page setup if ($pSheet->getPageSetup()->isPrintAreaSet()) { $pSheet->getPageSetup()->setPrintArea($this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows)); } // Update worksheet: drawings $aDrawings = $pSheet->getDrawingCollection(); foreach ($aDrawings as $objDrawing) { $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows); if ($objDrawing->getCoordinates() != $newReference) { $objDrawing->setCoordinates($newReference); } } // Update workbook: named ranges if (count($pSheet->getParent()->getNamedRanges()) > 0) { foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) { $namedRange->setRange($this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows)); } } } // Garbage collect $pSheet->garbageCollect(); }
protected function writeCell($value, $column, $row, $config) { // auto type if (!isset($config['type']) || $config['type'] === null) { $this->sheet->setCellValueByColumnAndRow($column, $row, $value); } elseif ($config['type'] === 'date') { if (!is_int($value)) { $timestamp = strtotime($value); } $this->sheet->SetCellValueByColumnAndRow($column, $row, \PHPExcel_Shared_Date::PHPToExcel($timestamp)); if (!isset($config['styles']['numberformat']['code'])) { $config['styles']['numberformat']['code'] = $this->defaultDateFormat; } } elseif ($config['type'] === 'url') { if (isset($config['label'])) { if ($config['label'] instanceof \Closure) { // NOTE: calculate label on top level $label = call_user_func($config['label']); } else { $label = $config['label']; } } else { $label = $value; } $urlValid = filter_var($value, FILTER_VALIDATE_URL) !== false; if (!$urlValid) { $label = ''; } $this->sheet->setCellValueByColumnAndRow($column, $row, $label); if ($urlValid) { $this->sheet->getCellByColumnAndRow($column, $row)->getHyperlink()->setUrl($value); } } else { $this->sheet->setCellValueExplicitByColumnAndRow($column, $row, $value, $config['type']); } if (isset($config['styles'])) { $this->sheet->getStyleByColumnAndRow($column, $row)->applyFromArray($config['styles']); } }
public function getNextDataset() { $dataset = new Dataset(); for ($col = 0; $col < $this->highestColumnIndex; ++$col) { $cell = $this->worksheet->getCellByColumnAndRow($col, $this->rowPointer); $dataset->add($this->header[$col], $cell->getValue()); } $this->rowPointer++; return $dataset; }
/** * 行を完全コピーする * * http://blog.kotemaru.org/old/2012/04/06.html より * @param PHPExcel_Worksheet $sheet * @param int $srcRow * @param int $dstRow * @param int $height * @param int $width * @throws PHPExcel_Exception */ function copyRows(PHPExcel_Worksheet $sheet, $srcRow, $dstRow, $height, $width) { for ($row = 0; $row < $height; $row++) { // セルの書式と値の複製 for ($col = 0; $col < $width; $col++) { $cell = $sheet->getCellByColumnAndRow($col, $srcRow + $row); $style = $sheet->getStyleByColumnAndRow($col, $srcRow + $row); $dstCell = PHPExcel_Cell::stringFromColumnIndex($col) . (string) ($dstRow + $row); $sheet->setCellValue($dstCell, $cell->getValue()); $sheet->duplicateStyle($style, $dstCell); } // 行の高さ複製。 $h = $sheet->getRowDimension($srcRow + $row)->getRowHeight(); $sheet->getRowDimension($dstRow + $row)->setRowHeight($h); } // セル結合の複製 // - $mergeCell="AB12:AC15" 複製範囲の物だけ行を加算して復元。 // - $merge="AB16:AC19" foreach ($sheet->getMergeCells() as $mergeCell) { $mc = explode(":", $mergeCell); $col_s = preg_replace("/[0-9]*/", "", $mc[0]); $col_e = preg_replace("/[0-9]*/", "", $mc[1]); $row_s = (int) preg_replace("/[A-Z]*/", "", $mc[0]) - $srcRow; $row_e = (int) preg_replace("/[A-Z]*/", "", $mc[1]) - $srcRow; // 複製先の行範囲なら。 if (0 <= $row_s && $row_s < $height) { $merge = $col_s . (string) ($dstRow + $row_s) . ":" . $col_e . (string) ($dstRow + $row_e); $sheet->mergeCells($merge); } } }
/** * * @param DOMElement $element * @return PHPExcel_Cell */ protected function _addCell($element, $row = null) { $text = trim($element->nodeValue); $cell = $this->_mainSheet->getCellByColumnAndRow($this->_currentCell, $this->_currentRow); if (preg_match('/^\\$ *(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$/', $text)) { $currencyCode = PHPExcel_Shared_String::getCurrencyCode(); $decimalSeparator = PHPExcel_Shared_String::getDecimalSeparator(); $thousandsSeparator = PHPExcel_Shared_String::getThousandsSeparator(); $value = (double) trim(str_replace(array($currencyCode, $thousandsSeparator, $decimalSeparator), array('', '', '.'), $text)); $cell->setValueExplicit($value, PHPExcel_Cell_DataType::TYPE_NUMERIC); //Style $cell->getWorksheet()->getStyle($cell->getCoordinate())->getNumberFormat()->setFormatCode(str_replace('$', $currencyCode, PHPExcel_Style_NumberFormat::FORMAT_CURRENCY_USD_SIMPLE)); } else { $cell->setValueExplicit($text, PHPExcel_Cell_DataType::TYPE_STRING); } $currentCell = $this->_currentCell; if ($element->hasAttribute('colspan')) { $colspan = (int) $element->getAttribute('colspan'); $cellTarget = $this->_currentCell + $colspan - 1; $this->_mainSheet->mergeCellsByColumnAndRow($this->_currentCell, $this->_currentRow, $cellTarget, $this->_currentRow); $this->_currentCell += $colspan; } else { $this->_currentCell++; } if ($element->hasAttribute('rowspan')) { $rowSpan = (int) $element->getAttribute('rowspan'); if ($rowSpan < 2) { return $cell; } $rowTarget = $this->_currentRow + ($rowSpan - 1); $this->_mainSheet->mergeCellsByColumnAndRow($currentCell, $this->_currentRow, $currentCell, $rowTarget); } return $cell; }
/** * @param $columnNumber * @param $columnIdentifier * @param $type */ protected function doCellStyling($columnNumber, $columnIdentifier, $type) { $excelSettings = $this->getExcelSettingsByColumnIdentifier($columnIdentifier); if (!is_array($excelSettings[$type])) { return; } $settings = $excelSettings[$type]; if ($settings['dataType']) { $this->activeSheet->getCellByColumnAndRow($columnNumber, $this->rowNumber)->setDataType($settings['dataType']); } if ($settings['wrapText']) { $this->activeSheet->getStyleByColumnAndRow($columnNumber, $this->rowNumber)->getAlignment()->setWrapText($settings['wrapText']); } if ($settings['vertical']) { $this->activeSheet->getStyleByColumnAndRow($columnNumber, $this->rowNumber)->getAlignment()->setVertical($settings['vertical']); } if ($settings['shrinkToFit']) { $this->activeSheet->getStyleByColumnAndRow($columnNumber, $this->rowNumber)->getAlignment()->setShrinkToFit($settings['shrinkToFit']); } if ($type == 'body') { if (!array_key_exists($columnIdentifier, $this->bodyCellStyleCache)) { $this->bodyCellStyleCache[$columnIdentifier] = $this->buildStyleArray($settings); } $this->activeSheet->getStyleByColumnAndRow($columnNumber, $this->rowNumber)->applyFromArray($this->bodyCellStyleCache[$columnIdentifier]); } else { $this->activeSheet->getStyleByColumnAndRow($columnNumber, $this->rowNumber)->applyFromArray($this->buildStyleArray($settings)); } }
/** * Проверить не является ли строка заголовком, т.к. ТОРГ12 может содержать несколько заголовков * * @param int $rowNumber Номер строки * @param array $currentRow Содержимое строки * @return bool */ private function validateRow($rowNumber, $currentRow) { $row = []; $key = 1; for ($col = 0; $col <= $this->highestColumn; $col++) { $currentCell = $this->normalizeCellValue($this->worksheet->getCellByColumnAndRow($col, $rowNumber)->getValue()); // запишем непустые значения в массив для текущей строки if ($currentCell) { $row[$key++] = $currentCell; } } // пропускаем строку с номерами столбцов if (count($row) > 2 && ($row[1] == 1 && $row[2] == 2 && $row[3] == 3)) { return false; } // пропускаем строку без порядкового номера if (!intval($currentRow['num'])) { return false; } // пропускаем повторные заголовки (достаточно, если в двух столбцах будет заголовок) if (in_array($currentRow['code'], $this->settingsRow['code']) || in_array($currentRow['num'], $this->settingsRow['num'])) { return false; } return true; }
/** * Sets a date/time value at the given col,row location * * @param $object the raw data value object */ protected function setTimeDataValue(\SMWTimeValue $object) { $type = PHPExcel_Cell_DataType::TYPE_NUMERIC; $value = \PHPExcel_Shared_Date::stringToExcel(str_replace('T', ' ', $object->getISO8601Date())); $this->sheet->getCellByColumnAndRow($this->colNum, $this->rowNum)->setValueExplicit($value, $type); if (!$this->styled) { $this->sheet->getStyleByColumnAndRow($this->colNum, $this->rowNum)->getNumberFormat()->setFormatCode(\PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY); } }
/** * Current PHPExcel_Cell * * @return PHPExcel_Cell */ public function current() { $cellExists = $this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex); if ($this->_onlyExistingCells && $cellExists || !$this->_onlyExistingCells) { return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); } else { if ($this->_onlyExistingCells && !$cellExists) { // Loop untill we find one while ($this->valid()) { $this->next(); if ($this->_subject->cellExistsByColumnAndRow($this->_position, $this->_rowIndex)) { return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); } } } } return null; }
/** * Current PHPExcel_Cell * * @return PHPExcel_Cell */ public function current() { return $this->_subject->getCellByColumnAndRow($this->_position, $this->_rowIndex); }
/** * Get date from Excel sheet for given column and row. Convert Excel date to format acceptable by TimeExpressionParser if necessary. * @param PHPExcel_Worksheet $po_sheet The work sheet * @param int $pn_row_num row number (zero indexed) * @param string|int $pm_col either column number (zero indexed) or column letter ('A', 'BC') * @param int $pn_offset Offset to adf to the timestamp (can be used to fix timezone issues or simple to move dates around a little bit) * @return string|null the date, if a value exists */ function caPhpExcelGetDateCellContent($po_sheet, $pn_row_num, $pm_col, $pn_offset = 0) { if (!is_int($pn_offset)) { $pn_offset = 0; } if (!is_numeric($pm_col)) { $pm_col = PHPExcel_Cell::columnIndexFromString($pm_col) - 1; } $o_val = $po_sheet->getCellByColumnAndRow($pm_col, $pn_row_num); $vs_val = trim((string) $o_val); if (strlen($vs_val) > 0) { $vn_timestamp = PHPExcel_Shared_Date::ExcelToPHP(trim((string) $o_val->getValue())) + $pn_offset; if (!($vs_return = caGetLocalizedDate($vn_timestamp, array('dateFormat' => 'iso8601', 'timeOmit' => false)))) { $vs_return = $vs_val; } } else { $vs_return = null; } return $vs_return; }
/** * Get raw cell from Excel sheet for given column and row * @param PHPExcel_Worksheet $po_sheet The work sheet * @param int $pn_row_num row number (zero indexed) * @param string|int $pm_col either column number (zero indexed) or column letter ('A', 'BC') * @return PHPExcel_Cell|null the cell, if a value exists */ function caPhpExcelGetRawCell($po_sheet, $pn_row_num, $pm_col) { if (!is_numeric($pm_col)) { $pm_col = PHPExcel_Cell::columnIndexFromString($pm_col) - 1; } return $po_sheet->getCellByColumnAndRow($pm_col, $pn_row_num); }
/** * Write one url somewhere in the worksheet. * * @param integer $row Zero indexed row * @param integer $col Zero indexed column * @param string $url The url to write * @param mixed $format The XF format for the cell */ public function write_url($row, $col, $url, $format = null) { $this->worksheet->setCellValueByColumnAndRow($col, $row + 1, $url); $this->worksheet->getCellByColumnAndRow($col, $row + 1)->getHyperlink()->setUrl($url); $this->apply_format($row, $col, $format); }
function lastRow(PHPExcel_Worksheet $sheet, $indexCellDAY) { //получаем индекс последней строки в ЛИСТЕ $higestRow = $sheet->getHighestRow(); for ($i = $indexCellDAY; $i <= $higestRow; $i++) { $tempRow = $sheet->getCellByColumnAndRow(0, $i)->getFormattedValue(); if (mb_strtoupper(trim($tempRow)) == "СУББОТА") { return ++$i; } } }
protected function _getCellValue($col, $row) { $value = $this->_sheet->getCellByColumnAndRow($col, $row)->getFormattedValue(); return $value; //return trim(iconv('windows-1251','utf-8',$value)); }
/** * Insert a new column or row, updating all possible related data * * @param string $pBefore Insert before this cell address (e.g. 'A1') * @param integer $pNumCols Number of columns to insert/delete (negative values indicate deletion) * @param integer $pNumRows Number of rows to insert/delete (negative values indicate deletion) * @param PHPExcel_Worksheet $pSheet The worksheet that we're editing * @throws PHPExcel_Exception */ public function insertNewBefore($pBefore = 'A1', $pNumCols = 0, $pNumRows = 0, PHPExcel_Worksheet $pSheet = NULL) { $remove = $pNumCols < 0 || $pNumRows < 0; $aCellCollection = $pSheet->getCellCollection(); // Get coordinates of $pBefore $beforeColumn = 'A'; $beforeRow = 1; list($beforeColumn, $beforeRow) = PHPExcel_Cell::coordinateFromString($pBefore); $beforeColumnIndex = PHPExcel_Cell::columnIndexFromString($beforeColumn); // Clear cells if we are removing columns or rows $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); // 1. Clear column strips if we are removing columns if ($pNumCols < 0 && $beforeColumnIndex - 2 + $pNumCols > 0) { for ($i = 1; $i <= $highestRow - 1; ++$i) { for ($j = $beforeColumnIndex - 1 + $pNumCols; $j <= $beforeColumnIndex - 2; ++$j) { $coordinate = PHPExcel_Cell::stringFromColumnIndex($j) . $i; $pSheet->removeConditionalStyles($coordinate); if ($pSheet->cellExists($coordinate)) { $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); $pSheet->getCell($coordinate)->setXfIndex(0); } } } } // 2. Clear row strips if we are removing rows if ($pNumRows < 0 && $beforeRow - 1 + $pNumRows > 0) { for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { for ($j = $beforeRow + $pNumRows; $j <= $beforeRow - 1; ++$j) { $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . $j; $pSheet->removeConditionalStyles($coordinate); if ($pSheet->cellExists($coordinate)) { $pSheet->getCell($coordinate)->setValueExplicit('', PHPExcel_Cell_DataType::TYPE_NULL); $pSheet->getCell($coordinate)->setXfIndex(0); } } } } // Loop through cells, bottom-up, and change cell coordinates while ($cellID = $remove ? array_shift($aCellCollection) : array_pop($aCellCollection)) { $cell = $pSheet->getCell($cellID); $cellIndex = PHPExcel_Cell::columnIndexFromString($cell->getColumn()); if ($cellIndex - 1 + $pNumCols < 0) { continue; } // New coordinates $newCoordinates = PHPExcel_Cell::stringFromColumnIndex($cellIndex - 1 + $pNumCols) . ($cell->getRow() + $pNumRows); // Should the cell be updated? Move value and cellXf index from one cell to another. if ($cellIndex >= $beforeColumnIndex && $cell->getRow() >= $beforeRow) { // Update cell styles $pSheet->getCell($newCoordinates)->setXfIndex($cell->getXfIndex()); // Insert this cell at its new location if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { // Formula should be adjusted $pSheet->getCell($newCoordinates)->setValue($this->updateFormulaReferences($cell->getValue(), $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); } else { // Formula should not be adjusted $pSheet->getCell($newCoordinates)->setValue($cell->getValue()); } // Clear the original cell $pSheet->getCellCacheController()->deleteCacheData($cellID); } else { /* We don't need to update styles for rows/columns before our insertion position, but we do still need to adjust any formulae in those cells */ if ($cell->getDataType() == PHPExcel_Cell_DataType::TYPE_FORMULA) { // Formula should be adjusted $cell->setValue($this->updateFormulaReferences($cell->getValue(), $pBefore, $pNumCols, $pNumRows, $pSheet->getTitle())); } } } // Duplicate styles for the newly inserted cells $highestColumn = $pSheet->getHighestColumn(); $highestRow = $pSheet->getHighestRow(); if ($pNumCols > 0 && $beforeColumnIndex - 2 > 0) { for ($i = $beforeRow; $i <= $highestRow - 1; ++$i) { // Style $coordinate = PHPExcel_Cell::stringFromColumnIndex($beforeColumnIndex - 2) . $i; if ($pSheet->cellExists($coordinate)) { $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? $pSheet->getConditionalStyles($coordinate) : false; for ($j = $beforeColumnIndex - 1; $j <= $beforeColumnIndex - 2 + $pNumCols; ++$j) { $pSheet->getCellByColumnAndRow($j, $i)->setXfIndex($xfIndex); if ($conditionalStyles) { $cloned = array(); foreach ($conditionalStyles as $conditionalStyle) { $cloned[] = clone $conditionalStyle; } $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($j) . $i, $cloned); } } } } } if ($pNumRows > 0 && $beforeRow - 1 > 0) { for ($i = $beforeColumnIndex - 1; $i <= PHPExcel_Cell::columnIndexFromString($highestColumn) - 1; ++$i) { // Style $coordinate = PHPExcel_Cell::stringFromColumnIndex($i) . ($beforeRow - 1); if ($pSheet->cellExists($coordinate)) { $xfIndex = $pSheet->getCell($coordinate)->getXfIndex(); $conditionalStyles = $pSheet->conditionalStylesExists($coordinate) ? $pSheet->getConditionalStyles($coordinate) : false; for ($j = $beforeRow; $j <= $beforeRow - 1 + $pNumRows; ++$j) { $pSheet->getCell(PHPExcel_Cell::stringFromColumnIndex($i) . $j)->setXfIndex($xfIndex); if ($conditionalStyles) { $cloned = array(); foreach ($conditionalStyles as $conditionalStyle) { $cloned[] = clone $conditionalStyle; } $pSheet->setConditionalStyles(PHPExcel_Cell::stringFromColumnIndex($i) . $j, $cloned); } } } } } // Update worksheet: column dimensions $this->_adjustColumnDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: row dimensions $this->_adjustRowDimensions($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: page breaks $this->_adjustPageBreaks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: comments $this->_adjustComments($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: hyperlinks $this->_adjustHyperlinks($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: data validations $this->_adjustDataValidations($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: merge cells $this->_adjustMergeCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: protected cells $this->_adjustProtectedCells($pSheet, $pBefore, $beforeColumnIndex, $pNumCols, $beforeRow, $pNumRows); // Update worksheet: autofilter $autoFilter = $pSheet->getAutoFilter(); $autoFilterRange = $autoFilter->getRange(); if (!empty($autoFilterRange)) { if ($pNumCols != 0) { $autoFilterColumns = array_keys($autoFilter->getColumns()); if (count($autoFilterColumns) > 0) { sscanf($pBefore, '%[A-Z]%d', $column, $row); $columnIndex = PHPExcel_Cell::columnIndexFromString($column); list($rangeStart, $rangeEnd) = PHPExcel_Cell::rangeBoundaries($autoFilterRange); if ($columnIndex <= $rangeEnd[0]) { if ($pNumCols < 0) { // If we're actually deleting any columns that fall within the autofilter range, // then we delete any rules for those columns $deleteColumn = $columnIndex + $pNumCols - 1; $deleteCount = abs($pNumCols); for ($i = 1; $i <= $deleteCount; ++$i) { if (in_array(PHPExcel_Cell::stringFromColumnIndex($deleteColumn), $autoFilterColumns)) { $autoFilter->clearColumn(PHPExcel_Cell::stringFromColumnIndex($deleteColumn)); } ++$deleteColumn; } } $startCol = $columnIndex > $rangeStart[0] ? $columnIndex : $rangeStart[0]; // Shuffle columns in autofilter range if ($pNumCols > 0) { // For insert, we shuffle from end to beginning to avoid overwriting $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol - 1); $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol + $pNumCols - 1); $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); $startColRef = $startCol; $endColRef = $rangeEnd[0]; $toColRef = $rangeEnd[0] + $pNumCols; do { $autoFilter->shiftColumn(PHPExcel_Cell::stringFromColumnIndex($endColRef - 1), PHPExcel_Cell::stringFromColumnIndex($toColRef - 1)); --$endColRef; --$toColRef; } while ($startColRef <= $endColRef); } else { // For delete, we shuffle from beginning to end to avoid overwriting $startColID = PHPExcel_Cell::stringFromColumnIndex($startCol - 1); $toColID = PHPExcel_Cell::stringFromColumnIndex($startCol + $pNumCols - 1); $endColID = PHPExcel_Cell::stringFromColumnIndex($rangeEnd[0]); do { $autoFilter->shiftColumn($startColID, $toColID); ++$startColID; ++$toColID; } while ($startColID != $endColID); } } } } $pSheet->setAutoFilter($this->updateCellReference($autoFilterRange, $pBefore, $pNumCols, $pNumRows)); } // Update worksheet: freeze pane if ($pSheet->getFreezePane() != '') { $pSheet->freezePane($this->updateCellReference($pSheet->getFreezePane(), $pBefore, $pNumCols, $pNumRows)); } // Page setup if ($pSheet->getPageSetup()->isPrintAreaSet()) { $pSheet->getPageSetup()->setPrintArea($this->updateCellReference($pSheet->getPageSetup()->getPrintArea(), $pBefore, $pNumCols, $pNumRows)); } // Update worksheet: drawings $aDrawings = $pSheet->getDrawingCollection(); foreach ($aDrawings as $objDrawing) { $newReference = $this->updateCellReference($objDrawing->getCoordinates(), $pBefore, $pNumCols, $pNumRows); if ($objDrawing->getCoordinates() != $newReference) { $objDrawing->setCoordinates($newReference); } } // Update workbook: named ranges if (count($pSheet->getParent()->getNamedRanges()) > 0) { foreach ($pSheet->getParent()->getNamedRanges() as $namedRange) { if ($namedRange->getWorksheet()->getHashCode() == $pSheet->getHashCode()) { $namedRange->setRange($this->updateCellReference($namedRange->getRange(), $pBefore, $pNumCols, $pNumRows)); } } } // Garbage collect $pSheet->garbageCollect(); }
/** * Функция преобразования листа Excel в таблицу MySQL, с учетом объединенных строк и столбцов. Значения берутся уже вычисленными * * @param PHPExcel_Worksheet $worksheet - Лист Excel * @param string $table_name - Имя таблицы MySQL * @param int|array $columns_names - Строка или массив с именами столбцов таблицы MySQL (0 - имена типа column + n). Если указано больше столбцов, чем на листе Excel, будут использованы значения по умолчанию указанных типов столбцов. Если указано ложное значение (null, false, "", 0, -1...) столбец игнорируется * @param bool|int $start_row_index - Номер строки, с которой начинается обработка данных (например, если 1 строка шапка таблицы). Нумерация начинается с 1, как в Excel * @param bool|array $condition_functions - Массив функций с условиями добавления строки по значению столбца (столбец => функция) * @param bool|array $transform_functions - Массив функций для изменения значения столбца (столбец => функция) * @param bool|int $unique_column_for_update - Номер столбца с уникальным значением для обновления таблицы. Работает если $columns_names - массив (название столбца берется из него по [$unique_column_for_update - 1]) * @param bool|array $table_types - Типы столбцов таблицы (используется при создании таблицы), в SQL формате - "INT(11) NOT NULL". Если не указаны, то используется "TEXT NOT NULL" * @param bool|array $table_keys - Ключевые поля таблицы (тип => столбец) * @param string $table_encoding - Кодировка таблицы MySQL * @param string $table_engine - Тип таблицы MySQL * * @return bool - Флаг, удалось ли выполнить функцию в полном объеме */ private function excel_to_mysql($worksheet, $table_name, $columns_names, $start_row_index, $condition_functions, $transform_functions, $unique_column_for_update, $table_types, $table_keys, $table_encoding, $table_engine) { // Проверяем соединение с MySQL if (!$this->mysql_connect->connect_error) { // Строка для названий столбцов таблицы MySQL $columns = array(); // Количество столбцов на листе Excel $columns_count = \PHPExcel_Cell::columnIndexFromString($worksheet->getHighestColumn()); // Если в качестве имен столбцов передан массив, то проверяем соответствие его длинны с количеством столбцов if ($columns_names) { if (is_array($columns_names)) { $columns_names_count = count($columns_names); if ($columns_names_count < $columns_count) { return false; } elseif ($columns_names_count > $columns_count) { $columns_count = $columns_names_count; } } else { return false; } } // Если указаны типы столбцов if ($table_types) { if (is_array($table_types)) { // Проверяем количество столбцов и типов if (count($table_types) != count($columns_names)) { return false; } } else { return false; } } $table_name = "`{$table_name}`"; // Проверяем, что $columns_names - массив и $unique_column_for_update находиться в его пределах if ($unique_column_for_update) { $unique_column_for_update = is_array($columns_names) ? $unique_column_for_update <= count($columns_names) ? "`{$columns_names[$unique_column_for_update - 1]}`" : false : false; } // Перебираем столбцы листа Excel и генерируем строку с именами через запятую for ($column = 0; $column < $columns_count; $column++) { $column_name = is_array($columns_names) ? $columns_names[$column] : ($columns_names == 0 ? "column{$column}" : $worksheet->getCellByColumnAndRow($column, $columns_names)->getValue()); $columns[] = $column_name ? "`{$column_name}`" : null; } $query_string = "DROP TABLE IF EXISTS {$table_name}"; if (defined("EXCEL_MYSQL_DEBUG")) { if (EXCEL_MYSQL_DEBUG) { var_dump($query_string); } } // Удаляем таблицу MySQL, если она существовала (если не указан столбец с уникальным значением для обновления) if ($unique_column_for_update ? true : $this->mysql_connect->query($query_string)) { $columns_types = $ignore_columns = array(); // Обходим столбцы и присваиваем типы foreach ($columns as $index => $value) { if ($value == null) { $ignore_columns[] = $index; unset($columns[$index]); } else { if ($table_types) { $columns_types[] = "{$value} {$table_types[$index]}"; } else { $columns_types[] = "{$value} TEXT NOT NULL"; } } } // Если указаны ключевые поля, то создаем массив ключей if ($table_keys) { $columns_keys = array(); foreach ($table_keys as $key => $value) { $columns_keys[] = "{$value} (`{$key}`)"; } $columns_keys_list = implode(", ", $columns_keys); $columns_keys = ", {$columns_keys_list}"; } else { $columns_keys = null; } $columns_types_list = implode(", ", $columns_types); $query_string = "CREATE TABLE IF NOT EXISTS {$table_name} ({$columns_types_list}{$columns_keys}) COLLATE = '{$table_encoding}' ENGINE = {$table_engine}"; if (defined("EXCEL_MYSQL_DEBUG")) { if (EXCEL_MYSQL_DEBUG) { var_dump($query_string); } } // Создаем таблицу MySQL if ($this->mysql_connect->query($query_string)) { // Коллекция значений уникального столбца для удаления несуществующих строк в файле импорта (используется при обновлении) $id_list_in_import = array(); // Количество строк на листе Excel $rows_count = $worksheet->getHighestRow(); // Получаем массив всех объединенных ячеек $all_merged_cells = $worksheet->getMergeCells(); // Перебираем строки листа Excel for ($row = $start_row_index ? $start_row_index : (is_array($columns_names) ? 1 : $columns_names + 1); $row <= $rows_count; $row++) { // Строка со значениями всех столбцов в строке листа Excel $values = array(); // Перебираем столбцы листа Excel for ($column = 0; $column < $columns_count; $column++) { if (in_array($column, $ignore_columns)) { continue; } // Строка со значением объединенных ячеек листа Excel $merged_value = null; // Ячейка листа Excel $cell = $worksheet->getCellByColumnAndRow($column, $row); // Перебираем массив объединенных ячеек листа Excel foreach ($all_merged_cells as $merged_cells) { // Если текущая ячейка - объединенная, if ($cell->isInRange($merged_cells)) { // то вычисляем значение первой объединенной ячейки, и используем её в качестве значения текущей ячейки $merged_value = explode(":", $merged_cells); $merged_value = $worksheet->getCell($merged_value[0])->getValue(); break; } } // Проверяем, что ячейка не объединенная: если нет, то берем ее значение, иначе значение первой объединенной ячейки $value = strlen($merged_value) == 0 ? $cell->getValue() : $merged_value; // Если задан массив функций с условиями if ($condition_functions) { if (isset($condition_functions[$columns_names[$column]])) { // Проверяем условие if (!$condition_functions[$columns_names[$column]]($value)) { break; } } } $value = $transform_functions ? isset($transform_functions[$columns_names[$column]]) ? $transform_functions[$columns_names[$column]]($value) : $value : $value; $values[] = "'{$this->mysql_connect->real_escape_string($value)}'"; } // Если количество столбцов не равно количеству значений, значит строка не прошла проверку if ($columns_count - count($ignore_columns) != count($values)) { continue; } // Добавляем или проверяем обновлять ли значение $add_to_table = $unique_column_for_update ? false : true; // Если обновляем if ($unique_column_for_update) { // Объединяем массивы для простоты работы $columns_values = array_combine($columns, $values); // Сохраняем уникальное значение $id_list_in_import[] = $columns_values[$unique_column_for_update]; // Создаем условие выборки $where = " WHERE {$unique_column_for_update} = {$columns_values[$unique_column_for_update]}"; // Удаляем столбец выборки unset($columns_values[$unique_column_for_update]); $query_string = "SELECT COUNT(*) AS count FROM {$table_name}{$where}"; if (defined("EXCEL_MYSQL_DEBUG")) { if (EXCEL_MYSQL_DEBUG) { var_dump($query_string); } } // Проверяем есть ли запись в таблице $count = $this->mysql_connect->query($query_string); $count = $count->fetch_assoc(); // Если есть, то создаем запрос и обновляем if (intval($count['count']) != 0) { $set = array(); foreach ($columns_values as $column => $value) { $set[] = "{$column} = {$value}"; } $set_list = implode(", ", $set); $query_string = "UPDATE {$table_name} SET {$set_list}{$where}"; if (defined("EXCEL_MYSQL_DEBUG")) { if (EXCEL_MYSQL_DEBUG) { var_dump($query_string); } } if (!$this->mysql_connect->query($query_string)) { return false; } } else { $add_to_table = true; } } // Добавляем строку в таблицу MySQL if ($add_to_table) { $columns_list = implode(", ", $columns); $values_list = implode(", ", $values); $query_string = "INSERT INTO {$table_name} ({$columns_list}) VALUES ({$values_list})"; if (defined("EXCEL_MYSQL_DEBUG")) { if (EXCEL_MYSQL_DEBUG) { var_dump($query_string); } } if (!$this->mysql_connect->query($query_string)) { return false; } } } if (!empty($id_list_in_import)) { $id_list = implode(", ", $id_list_in_import); $query_string = "DELETE FROM {$table_name} WHERE {$unique_column_for_update} NOT IN ({$id_list})"; if (defined("EXCEL_MYSQL_DEBUG")) { if (EXCEL_MYSQL_DEBUG) { var_dump($query_string); } } $this->mysql_connect->query($query_string); } return true; } } } return false; }
/** * Validate and return the header of the Excel file * * @param \PHPExcel_Worksheet $worksheet * @return string[] * @throws ImporterException */ protected function validateHeader(\PHPExcel_Worksheet $worksheet) { $row = 1; $col = 0; $headers = array(); do { $value = $worksheet->getCellByColumnAndRow($col, $row)->getValue(); if ($value) { $headers[$col++] = $value; } } while ($value); $valid = true; if ($col <= count(static::$fixedHeader)) { $valid = false; } else { foreach (static::$fixedHeader as $key => $value) { if ($headers[$key] != $value) { $valid = false; } } } if (!$valid) { throw new ImporterException('The header of the Excel file is invalid'); } return $headers; }