@@ -1535,6 +1535,115 @@ public void InsertColumns(string startColumn, int numberOfColumns)
1535
1535
_worksheetPart . Worksheet . Save ( ) ;
1536
1536
}
1537
1537
1538
+ /// <summary>
1539
+ /// Gets the column heading for a specified cell in the worksheet.
1540
+ /// </summary>
1541
+ /// <param name="cellName">The name of the cell (e.g., "A1").</param>
1542
+ /// <returns>The text of the column heading, or null if the column does not exist.</returns>
1543
+ /// <exception cref="ArgumentException">Thrown when the cellName is null or empty.</exception>
1544
+ /// <exception cref="InvalidOperationException">Thrown when the WorkbookPart is not found, the sheet is not found,
1545
+ /// the column name is invalid, no header cell is found, or the SharedStringTablePart is missing.</exception>
1546
+ /// <exception cref="IndexOutOfRangeException">Thrown when the shared string index is out of range.</exception>
1547
+ public string ? GetColumnHeadingNew ( string cellName )
1548
+ {
1549
+ if ( string . IsNullOrEmpty ( cellName ) )
1550
+ throw new ArgumentException ( "Cell name cannot be null or empty." , nameof ( cellName ) ) ;
1551
+
1552
+ var workbookPart = _worksheetPart . GetParentParts ( ) . OfType < WorkbookPart > ( ) . FirstOrDefault ( ) ;
1553
+ if ( workbookPart == null )
1554
+ throw new InvalidOperationException ( "No WorkbookPart found." ) ;
1555
+
1556
+ var sheets = workbookPart . Workbook . Descendants < DocumentFormat . OpenXml . Spreadsheet . Sheet > ( ) ;
1557
+ var sheet = sheets . FirstOrDefault ( s => workbookPart . GetPartById ( s . Id ) == _worksheetPart ) ;
1558
+
1559
+ if ( sheet == null )
1560
+ throw new InvalidOperationException ( "No matching sheet found for the provided WorksheetPart." ) ;
1561
+
1562
+ WorksheetPart worksheetPart = _worksheetPart ;
1563
+
1564
+ // Get the column name for the specified cell.
1565
+ string columnName = GetColumnName ( cellName ) ;
1566
+
1567
+ if ( string . IsNullOrEmpty ( columnName ) )
1568
+ throw new InvalidOperationException ( "Unable to determine the column name from the provided cell name." ) ;
1569
+
1570
+ // Get the cells in the specified column and order them by row.
1571
+ IEnumerable < DocumentFormat . OpenXml . Spreadsheet . Cell > cells = worksheetPart . Worksheet . Descendants < DocumentFormat . OpenXml . Spreadsheet . Cell > ( )
1572
+ . Where ( c => string . Compare ( GetColumnName ( c . CellReference ? . Value ) , columnName , true ) == 0 )
1573
+ . OrderBy ( r => GetRowIndexN ( r . CellReference ) ?? 0 ) ;
1574
+
1575
+ if ( ! cells . Any ( ) )
1576
+ {
1577
+ // The specified column does not exist.
1578
+ return null ;
1579
+ }
1580
+
1581
+ // Get the first cell in the column.
1582
+ DocumentFormat . OpenXml . Spreadsheet . Cell headCell = cells . First ( ) ;
1583
+
1584
+ if ( headCell == null )
1585
+ throw new InvalidOperationException ( "No header cell found in the specified column." ) ;
1586
+
1587
+ // If the content of the first cell is stored as a shared string, get the text of the first cell
1588
+ // from the SharedStringTablePart and return it. Otherwise, return the string value of the cell.
1589
+ if ( headCell . DataType != null && headCell . DataType . Value == CellValues . SharedString && int . TryParse ( headCell . CellValue ? . Text , out int index ) )
1590
+ {
1591
+ var sharedStringPart = workbookPart . GetPartsOfType < SharedStringTablePart > ( ) . FirstOrDefault ( ) ;
1592
+ if ( sharedStringPart == null )
1593
+ throw new InvalidOperationException ( "No SharedStringTablePart found." ) ;
1594
+
1595
+ var items = sharedStringPart . SharedStringTable . Elements < SharedStringItem > ( ) . ToArray ( ) ;
1596
+ if ( index < 0 || index >= items . Length )
1597
+ throw new IndexOutOfRangeException ( "Shared string index is out of range." ) ;
1598
+
1599
+ return items [ index ] . InnerText ;
1600
+ }
1601
+ else
1602
+ {
1603
+ return headCell . CellValue ? . Text ;
1604
+ }
1605
+ }
1606
+
1607
+
1608
+ /// <summary>
1609
+ /// Gets the row index from the specified cell name.
1610
+ /// </summary>
1611
+ /// <param name="cellName">The cell name in A1 notation (e.g., "A1").</param>
1612
+ /// <returns>The row index as a nullable unsigned integer, or null if the cell name is invalid.</returns>
1613
+ /// <exception cref="FormatException">Thrown when the row index portion of the cell name cannot be parsed.</exception>
1614
+ private uint ? GetRowIndexN ( string ? cellName )
1615
+ {
1616
+ if ( cellName is null )
1617
+ {
1618
+ return null ;
1619
+ }
1620
+
1621
+ // Create a regular expression to match the row index portion the cell name.
1622
+ Regex regex = new Regex ( @"\d+" ) ;
1623
+ Match match = regex . Match ( cellName ) ;
1624
+
1625
+ return uint . Parse ( match . Value ) ;
1626
+ }
1627
+
1628
+ /// <summary>
1629
+ /// Given a cell name, parses the specified cell to get the column name.
1630
+ /// </summary>
1631
+ /// <param name="cellName">The cell name in A1 notation (e.g., "A1").</param>
1632
+ /// <returns>The column name as a string, or an empty string if the cell name is invalid.</returns>
1633
+ private string GetColumnName ( string ? cellName )
1634
+ {
1635
+ if ( cellName is null )
1636
+ {
1637
+ return string . Empty ;
1638
+ }
1639
+
1640
+ // Create a regular expression to match the column name portion of the cell name.
1641
+ Regex regex = new Regex ( "[A-Za-z]+" ) ;
1642
+ Match match = regex . Match ( cellName ) ;
1643
+
1644
+ return match . Value ;
1645
+ }
1646
+
1538
1647
private static string IncrementColumnReference ( string reference , int columnCount )
1539
1648
{
1540
1649
var regex = new System . Text . RegularExpressions . Regex ( "([A-Za-z]+)(\\ d+)" ) ;
0 commit comments