我想将所有数据和某个范围的样式复制到其他单元格。例如,我想从A4:I15复制然后粘贴,我想复制A16中的内容和样式。我该怎么做?。这就是我要复制的内容:
我知道只复制数据而不是样式,并使用此代码执行:
$cellValues = $objPHPExcel->getActiveSheet()->rangeToArray('A4:I15');
$objPHPExcel->getActiveSheet()->fromArray($cellValues, null, 'A16');
我需要复制styes ..和数据
答案 0 :(得分:5)
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);
}
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);
}
}
}
$objPHPExcel = PHPExcel_IOFactory::load("x.xlsx");
$sheet = $objPHPExcel->getActiveSheet();
copyRows($sheet, 1, 50, 48, 11);
copyRows($sheet, 2, 7 + 5, 5, 5);
copyRows($sheet, 2, 7 + 10, 5, 5);
copyRows($sheet, 2, 7 + 15, 5, 5);
答案 1 :(得分:5)
更新:@pavelDD指出,自版本1.x.x以来,某些导入已重命名。我将分享新版本,而不是接受他对原始代码的编辑。除了重命名之外,我还修复了烦人的索引错误,并添加了一个从原始工作表复制样式的帮助程序。不幸的是,我太懒了,无法像上次那样将它从一个类转换为一个简单的函数。但根据以前的版本,如果需要,您应该能够自己做。
<?php
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
class Utils {
public static function copyRows( Worksheet $sheet, $srcRange, $dstCell, Worksheet $destSheet = null) {
if( !isset($destSheet)) {
$destSheet = $sheet;
}
if( !preg_match('/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/', $srcRange, $srcRangeMatch) ) {
// Invalid src range
return;
}
if( !preg_match('/^([A-Z]+)(\d+)$/', $dstCell, $destCellMatch) ) {
// Invalid dest cell
return;
}
$srcColumnStart = $srcRangeMatch[1];
$srcRowStart = $srcRangeMatch[2];
$srcColumnEnd = $srcRangeMatch[3];
$srcRowEnd = $srcRangeMatch[4];
$destColumnStart = $destCellMatch[1];
$destRowStart = $destCellMatch[2];
$srcColumnStart = Coordinate::columnIndexFromString($srcColumnStart);
$srcColumnEnd = Coordinate::columnIndexFromString($srcColumnEnd);
$destColumnStart = Coordinate::columnIndexFromString($destColumnStart);
$rowCount = 0;
for ($row = $srcRowStart; $row <= $srcRowEnd; $row++) {
$colCount = 0;
for ($col = $srcColumnStart; $col <= $srcColumnEnd; $col++) {
$cell = $sheet->getCellByColumnAndRow($col, $row);
$style = $sheet->getStyleByColumnAndRow($col, $row);
$dstCell = Coordinate::stringFromColumnIndex($destColumnStart + $colCount) . (string)($destRowStart + $rowCount);
$destSheet->setCellValue($dstCell, $cell->getValue());
$destSheet->duplicateStyle($style, $dstCell);
// Set width of column, but only once per column
if ($rowCount === 0) {
$w = $sheet->getColumnDimensionByColumn($col)->getWidth();
$destSheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setAutoSize(false);
$destSheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setWidth($w);
}
$colCount++;
}
$h = $sheet->getRowDimension($row)->getRowHeight();
$destSheet->getRowDimension($destRowStart + $rowCount)->setRowHeight($h);
$rowCount++;
}
foreach ($sheet->getMergeCells() as $mergeCell) {
$mc = explode(":", $mergeCell);
$mergeColSrcStart = Coordinate::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[0]));
$mergeColSrcEnd = Coordinate::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[1]));
$mergeRowSrcStart = ((int)preg_replace("/[A-Z]*/", "", $mc[0]));
$mergeRowSrcEnd = ((int)preg_replace("/[A-Z]*/", "", $mc[1]));
$relativeColStart = $mergeColSrcStart - $srcColumnStart;
$relativeColEnd = $mergeColSrcEnd - $srcColumnStart;
$relativeRowStart = $mergeRowSrcStart - $srcRowStart;
$relativeRowEnd = $mergeRowSrcEnd - $srcRowStart;
if (0 <= $mergeRowSrcStart && $mergeRowSrcStart >= $srcRowStart && $mergeRowSrcEnd <= $srcRowEnd) {
$targetColStart = Coordinate::stringFromColumnIndex($destColumnStart + $relativeColStart);
$targetColEnd = Coordinate::stringFromColumnIndex($destColumnStart + $relativeColEnd);
$targetRowStart = $destRowStart + $relativeRowStart;
$targetRowEnd = $destRowStart + $relativeRowEnd;
$merge = (string)$targetColStart . (string)($targetRowStart) . ":" . (string)$targetColEnd . (string)($targetRowEnd);
//Merge target cells
$destSheet->mergeCells($merge);
}
}
}
public static function copyStyleXFCollection(Spreadsheet $sourceSheet, Spreadsheet $destSheet) {
$collection = $sourceSheet->getCellXfCollection();
foreach ($collection as $key => $item) {
$destSheet->addCellXf($item);
}
}
}
?>
我已经采用了Prashant的答案并将其扩展以便于使用并添加了一些额外的功能。这是一个很好的资源来源。但它缺少一些关键功能: 取一个范围(例如A10:B15)而不仅仅是索引 拿一个目的地单元而不是一排。 设置目标列的宽度
请注意我正在使用PHPSpreadsheet,这是PHPExcel的继承者。 如果您使用的是旧版本,则只需更新Cell类的路径。
<?php
/**
* Copy range in PHPSpreadsheet/PHPExcel including styles
**/
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
function copyRange( Worksheet $sheet, $srcRange, $dstCell) {
// Validate source range. Examples: A2:A3, A2:AB2, A27:B100
if( !preg_match('/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/', $srcRange, $srcRangeMatch) ) {
// Wrong source range
return;
}
// Validate destination cell. Examples: A2, AB3, A27
if( !preg_match('/^([A-Z]+)(\d+)$/', $dstCell, $destCellMatch) ) {
// Wrong destination cell
return;
}
$srcColumnStart = $srcRangeMatch[1];
$srcRowStart = $srcRangeMatch[2];
$srcColumnEnd = $srcRangeMatch[3];
$srcRowEnd = $srcRangeMatch[4];
$destColumnStart = $destCellMatch[1];
$destRowStart = $destCellMatch[2];
// For looping purposes we need to convert the indexes instead
// Note: We need to subtract 1 since column are 0-based and not 1-based like this method acts.
$srcColumnStart = Cell::columnIndexFromString($srcColumnStart) - 1;
$srcColumnEnd = Cell::columnIndexFromString($srcColumnEnd) - 1;
$destColumnStart = Cell::columnIndexFromString($destColumnStart) - 1;
$rowCount = 0;
for ($row = $srcRowStart; $row <= $srcRowEnd; $row++) {
$colCount = 0;
for ($col = $srcColumnStart; $col <= $srcColumnEnd; $col++) {
$cell = $sheet->getCellByColumnAndRow($col, $row);
$style = $sheet->getStyleByColumnAndRow($col, $row);
$dstCell = Cell::stringFromColumnIndex($destColumnStart + $colCount) . (string)($destRowStart + $rowCount);
$sheet->setCellValue($dstCell, $cell->getValue());
$sheet->duplicateStyle($style, $dstCell);
// Set width of column, but only once per row
if ($rowCount === 0) {
$w = $sheet->getColumnDimensionByColumn($col)->getWidth();
$sheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setAutoSize(false);
$sheet->getColumnDimensionByColumn ($destColumnStart + $colCount)->setWidth($w);
}
$colCount++;
}
$h = $sheet->getRowDimension($row)->getRowHeight();
$sheet->getRowDimension($destRowStart + $rowCount)->setRowHeight($h);
$rowCount++;
}
foreach ($sheet->getMergeCells() as $mergeCell) {
$mc = explode(":", $mergeCell);
$mergeColSrcStart = Cell::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[0])) - 1;
$mergeColSrcEnd = Cell::columnIndexFromString(preg_replace("/[0-9]*/", "", $mc[1])) - 1;
$mergeRowSrcStart = ((int)preg_replace("/[A-Z]*/", "", $mc[0]));
$mergeRowSrcEnd = ((int)preg_replace("/[A-Z]*/", "", $mc[1]));
$relativeColStart = $mergeColSrcStart - $srcColumnStart;
$relativeColEnd = $mergeColSrcEnd - $srcColumnStart;
$relativeRowStart = $mergeRowSrcStart - $srcRowStart;
$relativeRowEnd = $mergeRowSrcEnd - $srcRowStart;
if (0 <= $mergeRowSrcStart && $mergeRowSrcStart >= $srcRowStart && $mergeRowSrcEnd <= $srcRowEnd) {
$targetColStart = Cell::stringFromColumnIndex($destColumnStart + $relativeColStart);
$targetColEnd = Cell::stringFromColumnIndex($destColumnStart + $relativeColEnd);
$targetRowStart = $destRowStart + $relativeRowStart;
$targetRowEnd = $destRowStart + $relativeRowEnd;
$merge = (string)$targetColStart . (string)($targetRowStart) . ":" . (string)$targetColEnd . (string)($targetRowEnd);
//Merge target cells
$sheet->mergeCells($merge);
}
}
}
?>
使用示例:
copyRange($sheet, 'A4:B8', 'E1');
copyRange($sheet, 'A4:B8', 'A10');
copyRange($sheet, 'A4:B8', 'C17');
注意:我没有尝试使用单个单元格。但理论上它应该适用于A1:A1
如果我犯了任何错误,或者随时编辑答案,请告诉我。
答案 2 :(得分:0)
我找到了没有其他代码的解决方案:
<?php
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Reader\BaseReader;
/** @var BaseReader $reader */
$reader = IOFactory::createReaderForFile('old_file.xlsx');
$reader->setReadDataOnly(false);
$spreadsheet = $reader->load('old_file.xlsx');
$worksheet = $spreadsheet->getActiveSheet();
/** Iterate needed cells in $worksheet and change their values **/
$writer = IOFactory::createWriter($spreadsheet, 'Xlsx');
$writer->save('new_file.xlsx');
重要的部分是设置选项 $ reader-> setReadDataOnly(false)(默认设置),因为如果将选项设置为true,则仅读取没有样式的数据。