using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; //using AsbSaubReport; //using AutoMapper; using System; using System.Linq; namespace ConsoleApp1 { //var options = new DbContextOptionsBuilder() // .UseNpgsql("Host=localhost;Database=postgres;Username=postgres;Password=q;Persist Security Info=True") // .Options; //var context = new AsbCloudDbContext(options); class Program { static void Main(/*string[] args*/) { using var firstExcel = SpreadsheetDocument.Open(@"D:\excels\excel1.xlsx", true); using var secondExcel = SpreadsheetDocument.Open(@"D:\excels\excel2.xlsx", true); using (var resultExcel = SpreadsheetDocument.Create(@"D:\excels\result.xlsx", SpreadsheetDocumentType.Workbook, true)) { var workbookPart = resultExcel.AddWorkbookPart(); workbookPart.Workbook = new Workbook(); var worksheetPart = workbookPart.AddNewPart(); worksheetPart.Worksheet = new Worksheet(); var sheets = workbookPart.Workbook.AppendChild(new Sheets()); var sharedStringTablePart = resultExcel.WorkbookPart. AddNewPart(); var stylesPart = resultExcel.WorkbookPart. AddNewPart(); //var sheet = new Sheet() //{ // Id = workbookPart.GetIdOfPart(worksheetPart), // SheetId = 1, // Name = "Test Sheet" //}; //sheets.Append(sheet); workbookPart.Workbook.Save(); } using (var resultExcel = SpreadsheetDocument.Open(@"D:\excels\result.xlsx", true)) { var resultExcelWorkSheetPart = resultExcel.WorkbookPart. WorksheetParts.First(); var resultExcelSheetData = resultExcelWorkSheetPart. Worksheet.AppendChild(new SheetData()); foreach (var sheet in firstExcel.WorkbookPart.Workbook.Descendants()) { var newSheet = new Sheet() { Id = resultExcel.WorkbookPart.GetIdOfPart(resultExcelWorkSheetPart), SheetId = sheet.SheetId.Value, Name = sheet.Name }; resultExcel.WorkbookPart.Workbook.Sheets.Append(newSheet); var firstExcelWorkSheetPart = firstExcel.WorkbookPart. GetPartById(sheet.Id) as WorksheetPart; var firstExcelRows = firstExcelWorkSheetPart.Worksheet. Descendants(); // retrieved rows from source // Числовые ячейки хранятся как есть и переносятся без проблем, а вот значения строковых ячеек хранятся // в отдельной таблице. При этом в самой строковой ячейке хранится индекс этой строки в таблице // (чтоб не хранить кучу одинаковых строк в документе. Что-то вроде интернирования строк). // Тут как раз переносится клон этой таблицы из исходного файла в результирующий. var firstExcelStringTable = firstExcel.WorkbookPart.GetPartsOfType() .FirstOrDefault().SharedStringTable; resultExcel.WorkbookPart.SharedStringTablePart.SharedStringTable = firstExcelStringTable.CloneNode(true) as SharedStringTable; // Аналогично переносим таблицу стилей ячеек (жирный шрифт и прочее). // Иначе ячейки переносятся абсолютно обычными, без всякой стилизации. var stylesSheet = firstExcel.WorkbookPart.GetPartsOfType() .FirstOrDefault().Stylesheet; resultExcel.WorkbookPart.WorkbookStylesPart.Stylesheet = stylesSheet.CloneNode(true) as Stylesheet; // Клонируем ряды в новый файл (без клонирования они не вытаскиваются из общего дерева) foreach (var row in firstExcelRows) resultExcelSheetData.AppendChild(row.CloneNode(true)); } //for (uint i = 1; i < 10; i++) // fills cells fine //{ // var row = new Row(); // row.Append(new Cell { CellValue = new CellValue(i.ToString()) }); // sheetData.AppendChild(row.CloneNode(true)); //} } //resultExcel.Close(); Console.WriteLine("Done. Press any key to quit."); Console.ReadKey(); } } }