Écrire à Excel avec Open Xml donne problème après certaines colonnes

J'utilise C # avec Open XML Format SDK 2.0, essayant d'écrire un file de rapport Excel. Mon problème est lorsque je franchis la colonne Z (atteignant AA), le file est corrompu et ne peut pas être ouvert manuellement par l'user. Des idées?

static void Main(ssortingng[] args) { PortfolioReport report = new PortfolioReport("Keywords"); report.CreateReport(); } public PortfolioReport(ssortingng client) { ssortingng newFileName = path + client + ".xlsx"; if (File.Exists(newFileName)) { File.Delete(newFileName); } FileInfo newFile = new FileInfo(newFileName); using (ExcelPackage package = new ExcelPackage(newFile)) { ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Keywords"); package.Save(); } document = SpreadsheetDocument.Open(newFileName, true); wbPart = document.WorkbookPart; } static readonly ssortingng[] Columns = new[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ", "AK", "AL", "AM", "AN", "AO", "AP", "AQ", "AR", "AS", "AT", "AU", "AV", "AW", "AX", "AY", "AZ", "BA", "BB", "BC", "BD", "BE", "BF", "BG", "BH" }; public static ssortingng IndexToColumn(int index) { if (index < 0) throw new IndexOutOfRangeException("index must be a positive number"); return Columns[index]; } public static object GetPropValue(object src, ssortingng propName) { return src.GetType().GetProperty(propName).GetValue(src, null); } // Create a new Portfolio report public void CreateReport() { ssortingng wsName = "Report Summary"; wbPart.Workbook.Descendants<Sheet>().FirstOrDefault().Name = wsName; var currentUser = UsersInfo.Keywords; //set the domainAge KeywordsModule.SetYearsAndMonths(currentUser.Keywords); //set the url site relevency in words KeywordsModule.SetAverageUrlSiteRelevencyLiteral(currentUser.Keywords); //set a model for the excel which will convert the keyword to the custom model according to gui names List<KeywordModelForExcelExport> keywordsForExports = KeywordsModule.PrepreKeywordSforExport(currentUser.Keywords); //we set the column headings var properties = typeof(KeywordModelForExcelExport).GetProperties(); for (int i = 0; i < properties.Length; i++) { var cell = IndexToColumn(i) + 1; UpdateValue(wsName, cell, properties[i].Name, 0, true); } //now we set the keyword values int row = 2; foreach (var keywordForExport in keywordsForExports) { for (int i = 0; i < properties.Length; i++) { var val = GetPropValue(keywordForExport, properties[i].Name); var cell = IndexToColumn(i) + row; if (val != null) UpdateValue(wsName, cell, val.ToSsortingng(), 0, true); } row++; } // All done! Close and save the document. document.Close(); } // Given a Worksheet and an address (like "AZ254"), either return a cell reference, or // create the cell reference and return it. private Cell InsertCellInWorksheet(Worksheet ws, ssortingng addressName) { SheetData sheetData = ws.GetFirstChild<SheetData>(); Cell cell = null; UInt32 rowNumber = GetRowIndex(addressName); Row row = GetRow(sheetData, rowNumber); // If the cell you need already exists, return it. // If there is not a cell with the specified column name, insert one. Cell refCell = row.Elements<Cell>(). Where(c => c.CellReference.Value == addressName).FirstOrDefault(); if (refCell != null) { cell = refCell; } else { cell = CreateCell(row, addressName); } return cell; } private Cell CreateCell(Row row, Ssortingng address) { Cell cellResult; Cell refCell = null; // Cells must be in sequential order according to CellReference. Determine where to insert the new cell. foreach (Cell cell in row.Elements<Cell>()) { if (ssortingng.Compare(cell.CellReference.Value, address, true) > 0) { refCell = cell; break; } } cellResult = new Cell(); cellResult.CellReference = address; row.InsertBefore(cellResult, refCell); return cellResult; } private Row GetRow(SheetData wsData, UInt32 rowIndex) { var row = wsData.Elements<Row>(). Where(r => r.RowIndex.Value == rowIndex).FirstOrDefault(); if (row == null) { row = new Row(); row.RowIndex = rowIndex; wsData.Append(row); } return row; } private UInt32 GetRowIndex(ssortingng address) { ssortingng rowPart; UInt32 l; UInt32 result = 0; for (int i = 0; i < address.Length; i++) { if (UInt32.TryParse(address.Subssortingng(i, 1), out l)) { rowPart = address.Subssortingng(i, address.Length - i); if (UInt32.TryParse(rowPart, out l)) { result = l; break; } } } return result; } public bool UpdateValue(ssortingng sheetName, ssortingng addressName, ssortingng value, UInt32Value styleIndex, bool isSsortingng) { // Assume failure. bool updated = false; Sheet sheet = wbPart.Workbook.Descendants<Sheet>().Where((s) => s.Name == sheetName).FirstOrDefault(); if (sheet != null) { Worksheet ws = ((WorksheetPart)(wbPart.GetPartById(sheet.Id))).Worksheet; Cell cell = InsertCellInWorksheet(ws, addressName); if (isSsortingng) { // Either resortingeve the index of an existing ssortingng, // or insert the ssortingng into the shared ssortingng table // and get the index of the new item. int ssortingngIndex = InsertSharedSsortingngItem(wbPart, value); cell.CellValue = new CellValue(ssortingngIndex.ToSsortingng()); cell.DataType = new EnumValue<CellValues>(CellValues.SharedSsortingng); } else { cell.CellValue = new CellValue(value); cell.DataType = new EnumValue<CellValues>(CellValues.Number); } if (styleIndex > 0) cell.StyleIndex = styleIndex; // Save the worksheet. ws.Save(); updated = true; } return updated; } // Given the main workbook part, and a text value, insert the text into the shared // ssortingng table. Create the table if necessary. If the value already exists, return // its index. If it doesn't exist, insert it and return its new index. private int InsertSharedSsortingngItem(WorkbookPart wbPart, ssortingng value) { int index = 0; bool found = false; var ssortingngTablePart = wbPart.GetPartsOfType<SharedSsortingngTablePart>().FirstOrDefault(); // If the shared ssortingng table is missing, something's wrong. // Just return the index that you found in the cell. // Otherwise, look up the correct text in the table. if (ssortingngTablePart == null) { // Create it. ssortingngTablePart = wbPart.AddNewPart<SharedSsortingngTablePart>(); ssortingngTablePart.SharedSsortingngTable = new SharedSsortingngTable(); } var ssortingngTable = ssortingngTablePart.SharedSsortingngTable; // if (ssortingngTable == null) // { // ssortingngTable = new SharedSsortingngTable(); // } // Iterate through all the items in the SharedSsortingngTable. If the text already exists, return its index. foreach (SharedSsortingngItem item in ssortingngTable.Elements<SharedSsortingngItem>()) { if (item.InnerText == value) { found = true; break; } index += 1; } if (!found) { ssortingngTable.AppendChild(new SharedSsortingngItem(new Text(value))); ssortingngTable.Save(); } return index; } 

Votre command est interrompue dans CreateCell pour les references de cellule après Z Vous utilisez actuellement ssortingng.Compare mais cela fera une comparaison alpha, ce qui signifie que AA1 est avant Z1 plutôt que après.

Il existe plusieurs manières de réparer ceci: une façon serait de convertir la cellReference en un index de colonne, puis de les comparer au lieu de comparer les references cellulaires directement. Par exemple:

 private static int? GetColumnIndex(ssortingng cellRef) { if (ssortingng.IsNullOrEmpty(cellRef)) return null; cellRef = cellRef.ToUpper(); int columnIndex = -1; int mulitplier = 1; foreach (char c in cellRef.ToCharArray().Reverse()) { if (char.IsLetter(c)) { columnIndex += mulitplier * ((int)c - 64); mulitplier = mulitplier * 26; } } return columnIndex; } returnner nulle; private static int? GetColumnIndex(ssortingng cellRef) { if (ssortingng.IsNullOrEmpty(cellRef)) return null; cellRef = cellRef.ToUpper(); int columnIndex = -1; int mulitplier = 1; foreach (char c in cellRef.ToCharArray().Reverse()) { if (char.IsLetter(c)) { columnIndex += mulitplier * ((int)c - 64); mulitplier = mulitplier * 26; } } return columnIndex; } 

Ensuite, au lieu de

 if (ssortingng.Compare(cell.CellReference.Value, address, true) > 0) { refCell = cell; break; } 

Tu peux faire

 if (GetColumnIndex(cell.CellReference.Value) > GetColumnIndex(address)) { refCell = cell; break; }