Skip to content

Instantly share code, notes, and snippets.

@josephmate
Last active June 24, 2021 01:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josephmate/d46f2fcca8088c1a4bcec3d2fe62cd2a to your computer and use it in GitHub Desktop.
Save josephmate/d46f2fcca8088c1a4bcec3d2fe62cd2a to your computer and use it in GitHub Desktop.
fixed when replacing existing rows. previously only appending worked.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
namespace CopyRowOpenXML
{
class Program
{
static void Main(string[] args)
{
// backup the file incase we corrupt the file
string fromFile = "C:\\Users\\Joseph\\Desktop\\sample.xlsx";
string toFile = "C:\\Users\\Joseph\\Desktop\\sampleResult.xlsx";
if(System.IO.File.Exists(toFile)){
System.IO.File.Delete(toFile);
}
System.IO.File.Copy(fromFile, toFile);
// modify the backup
using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(toFile, true))
{
CopyRowsAndReplace(spreadsheetDocument, "Sheet1", 3, 5, 7);
spreadsheetDocument.Save();
}
Console.WriteLine("Done");
}
/// <summary>
/// Copies the rows in the document using the rows starting from 'srcRowFrom' until 'srcRowTo' (inclusive) and places them starting at 'destRowFrom'.
/// If there is data already in those rows, it will be overwritten.
/// </summary>
/// <param name="document">The document to take the rows from</param>
/// <param name="sheetName">The name of the sheet in the 'document' to take the rows from</param>
/// <param name="srcRowFrom">The index of the row to start copying from</param>
/// <param name="srcRowTo">The index of the final row to copy</param>
/// <param name="destRowFrom">Where to start placing the copied rows</param>
public static void CopyRowsAndReplace(SpreadsheetDocument document, string sheetName,
int srcRowFrom, int srcRowTo, int destRowFrom)
{
WorkbookPart workbookPart = document.WorkbookPart;
if (srcRowTo < srcRowFrom || destRowFrom < srcRowFrom) return;
int destRowFromBase = destRowFrom;
WorksheetPart worksheetPart = GetWorksheetPartByName(document, sheetName);
SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
// 1. Delete the existing rows if any are present.
int destRowTo = destRowFrom + (srcRowTo - srcRowFrom);
IList<Row> rowsToDelete = sheetData.Descendants<Row>()
.Where(r => r.RowIndex >= destRowFrom && r.RowIndex <= destRowTo)
.ToList<Row>();
foreach(Row row in rowsToDelete)
{
row.RemoveAllChildren();
}
// 2. Copy the rows
IList<Row> rowsToCopy = sheetData.Descendants<Row>()
.Where(r => r.RowIndex >= srcRowFrom && r.RowIndex <= srcRowTo)
.ToList<Row>();
int currentCopiedRow = destRowFrom;
foreach (Row row in rowsToCopy)
{
Row copiedRow = new Row() { RowIndex = new UInt32Value(Convert.ToUInt32(currentCopiedRow)) };
foreach(Cell cell in row.Elements<Cell>())
{
Cell copiedCell = new Cell() {
CellReference = new StringValue(GetColumnLetter(cell.CellReference.Value) + currentCopiedRow.ToString())
};
copiedCell.CellValue = new CellValue(cell.CellValue.Text);
copiedRow.Append(copiedCell);
}
sheetData.Append(copiedRow);
currentCopiedRow++;
}
}
private static WorksheetPart
GetWorksheetPartByName(SpreadsheetDocument document,
string sheetName)
{
IEnumerable<Sheet> sheets =
document.WorkbookPart.Workbook.GetFirstChild<Sheets>().
Elements<Sheet>().Where(s => s.Name == sheetName);
if (sheets.Count() == 0)
{
return null;
}
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)
document.WorkbookPart.GetPartById(relationshipId);
return worksheetPart;
}
private static string GetColumnLetter(string cellReference)
{
Regex regex = new Regex("[A-Za-z]+");
Match match = regex.Match(cellReference);
return match.Value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment