using DocumentFormat.OpenXml; using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; //using AsbSaubReport; //using AutoMapper; using System; using System.Collections.Generic; 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*/) { var sourceExcelPaths = new List { @"D:\excels\excel1.xlsx", @"D:\excels\excel2.xlsx" //@"D:\excels\e1.xlsx", //@"D:\excels\e2.xlsx", //@"D:\excels\e3.xlsx", //@"D:\excels\e4.xlsx", //@"D:\excels\e5.xlsx", //@"D:\excels\e6.xlsx" }; const string resultExcelPath = @"D:\excels\result.xlsx"; // result file create and init using (var resultExcelFile = SpreadsheetDocument.Create(resultExcelPath, SpreadsheetDocumentType.Workbook, true)) { var workbookPart = resultExcelFile.AddWorkbookPart(); workbookPart.Workbook = new Workbook(); workbookPart.Workbook.AppendChild(new Sheets()); resultExcelFile.WorkbookPart.AddNewPart(); resultExcelFile.WorkbookPart.SharedStringTablePart.SharedStringTable = new SharedStringTable(); resultExcelFile.WorkbookPart.AddNewPart(); workbookPart.Workbook.Save(); } foreach (var sourceExcelPath in sourceExcelPaths) { using var sourceExcelFile = SpreadsheetDocument.Open(sourceExcelPath, false); using var resultExcelFile = SpreadsheetDocument.Open(resultExcelPath, true); foreach (var sheet in sourceExcelFile.WorkbookPart.Workbook.Descendants()) { // Чтобы писать на новый лист, нужен новый WorkSheetPart, WorkSheet, SheetData и Sheet. // https://stackoverflow.com/questions/9120544/openxml-multiple-sheets var resultExcelWorkSheetPart = resultExcelFile.WorkbookPart.AddNewPart(); resultExcelWorkSheetPart.Worksheet = new Worksheet(); var resultExcelSheetData = resultExcelWorkSheetPart. Worksheet.AppendChild(new SheetData()); var newSheet = new Sheet() { Id = resultExcelFile.WorkbookPart.GetIdOfPart(resultExcelWorkSheetPart), SheetId = sheet.SheetId.Value, Name = sheet.Name }; resultExcelFile.WorkbookPart.Workbook.Sheets.Append(newSheet); var sourceWorkSheetPart = sourceExcelFile.WorkbookPart. GetPartById(sheet.Id) as WorksheetPart; // Не самая лучшая выборка рядов текущей страницы исходного файла. // Наверняка для этого есть метод. var sourceFileCurrentListRows = sourceWorkSheetPart.Worksheet.ChildElements .FirstOrDefault(w => w.LocalName == "sheetData").ChildElements; // Числовые ячейки хранятся как есть и переносятся без проблем, а вот значения строковых ячеек хранятся // в отдельной таблице. При этом в самой строковой ячейке хранится индекс этой строки в таблице // (чтоб не хранить кучу одинаковых строк в документе. Что-то вроде интернирования строк). // Тут как раз переносится клон этой таблицы из исходного файла в результирующий. // Разные всяческие Part'ы можно найти тут: // https://docs.microsoft.com/ru-ru/dotnet/api/documentformat.openxml.packaging.spreadsheetdocument.workbookpart?view=openxml-2.8.1 var sourceExcelStringTable = sourceExcelFile.WorkbookPart.GetPartsOfType() .FirstOrDefault().SharedStringTable; //resultExcelFile.WorkbookPart.SharedStringTablePart.SharedStringTable.Load(sourceExcelFile.WorkbookPart.SharedStringTablePart); //sourceExcelStringTable.CloneNode(true) as SharedStringTable; // Аналогично переносим таблицу стилей ячеек (жирный шрифт и прочее). // Иначе ячейки переносятся абсолютно обычными, без всякой стилизации. var stylesSheet = sourceExcelFile.WorkbookPart.GetPartsOfType() .FirstOrDefault().Stylesheet; resultExcelFile.WorkbookPart.WorkbookStylesPart.Stylesheet = stylesSheet.CloneNode(true) as Stylesheet; // Клонируем ряды в новый файл (без клонирования они не вытаскиваются из общего дерева) foreach (var row in sourceFileCurrentListRows) { var newCells = new List(); foreach(var c in row.ChildElements) { var cell = (Cell)c; if (cell.DataType is not null && cell.DataType.Value == CellValues.SharedString) { var cellValue = sourceExcelStringTable.ElementAt(int.Parse(cell.InnerText)).InnerText; newCells.Add(new Cell { CellReference = cell.CellReference, DataType = CellValues.String, CellValue = new CellValue(cellValue) }); } else newCells.Add(cell.CloneNode(true) as Cell); } var newRow = row.CloneNode(true); newRow.RemoveAllChildren(); newRow.Append(newCells); resultExcelSheetData.AppendChild(newRow); } } } Console.WriteLine("Done. Press any key to quit."); Console.ReadKey(); } } }