@@ -2629,13 +2629,14 @@ private static bool WorksheetExists(string name, Workbook workbook)
26292629
26302630 #endregion
26312631
2632- #region Insert-Search-Replace
2632+ #region Insert-Search-Replace
26332633
26342634 /// <summary>
2635- /// Inserts 'count' rows below the specified 'rowNumber'.
2636- /// The ' new' rows inherit the style of the row above .
2637- /// Note: Formulas are not adjusted.
2635+ /// Inserts 'count' rows below the specified 'rowNumber'. Existing cells are moved down by the number of new rows.
2636+ /// The inserted, new rows inherits the style of the original cell at the defined row number .
2637+ /// The inserted cells are empty. The values can be set later
26382638 /// </summary>
2639+ /// <remarks>Formulas / references are not adjusted</remarks>
26392640 /// <param name="rowNumber">Row number below which the new row(s) will be inserted.</param>
26402641 /// <param name="numberOfNewRows">Number of rows to insert.</param>
26412642 public void InsertRow ( int rowNumber , int numberOfNewRows )
@@ -2665,7 +2666,6 @@ public void InsertRow(int rowNumber, int numberOfNewRows)
26652666 this . Cells . Remove ( cell . Key ) ;
26662667 }
26672668
2668-
26692669 // Fill the gap with new cells, using the same style as the first row.
26702670 foreach ( Cell cell in upperRow )
26712671 {
@@ -2686,11 +2686,62 @@ public void InsertRow(int rowNumber, int numberOfNewRows)
26862686 }
26872687 }
26882688
2689+ /// <summary>
2690+ /// Inserts 'count' columns right of the specified 'columnNumber'. Existing cells are moved to the right by the number of new columns.
2691+ /// The inserted, new columns inherits the style of the original cell at the defined column number.
2692+ /// The inserted cells are empty. The values can be set later
2693+ /// </summary>
2694+ /// <remarks>Formulas are not adjusted</remarks>
2695+ /// <param name="columnNumber">Column number right which the new column(s) will be inserted.</param>
2696+ /// <param name="numberOfNewColumns">Number of columns to insert.</param>
2697+ public void InsertColumn ( int columnNumber , int numberOfNewColumns )
2698+ {
2699+ var leftColumn = this . GetColumn ( columnNumber ) ;
2700+ var cellsToChange = this . Cells . Where ( c => c . Value . CellAddress2 . Column > columnNumber ) . ToList ( ) ;
2701+
2702+ Dictionary < string , Cell > newCells = new Dictionary < string , Cell > ( ) ;
2703+ foreach ( var cell in cellsToChange )
2704+ {
2705+ var row = cell . Value . CellAddress2 . Row ;
2706+ var col = cell . Value . CellAddress2 . Column ;
2707+ Address newAddress = new Address ( col + numberOfNewColumns , row ) ;
2708+
2709+ Cell newCell = new Cell ( cell . Value . Value , cell . Value . DataType , newAddress ) ;
2710+ if ( cell . Value . CellStyle != null )
2711+ {
2712+ newCell . SetStyle ( cell . Value . CellStyle ) ; // Apply the style from the "old" cell.
2713+ }
2714+ newCells . Add ( newAddress . GetAddress ( ) , newCell ) ;
2715+
2716+ // Delete the original cells since the key cannot be changed.
2717+ this . Cells . Remove ( cell . Key ) ;
2718+ }
2719+
2720+ // Fill the gap with new cells, using the same style as the first row.
2721+ foreach ( Cell cell in leftColumn )
2722+ {
2723+ for ( int i = 0 ; i < numberOfNewColumns ; i ++ )
2724+ {
2725+ Address newAddress = new Address ( cell . CellAddress2 . Column + 1 + i , cell . CellAddress2 . Row ) ;
2726+ Cell newCell = new Cell ( null , Cell . CellType . EMPTY , newAddress ) ;
2727+ if ( cell . CellStyle != null )
2728+ newCell . SetStyle ( cell . CellStyle ) ;
2729+ this . Cells . Add ( newAddress . GetAddress ( ) , newCell ) ;
2730+ }
2731+ }
2732+
2733+ // Re-add the previous cells from the copy back with a new key.
2734+ foreach ( KeyValuePair < string , Cell > cellKeyValue in newCells )
2735+ {
2736+ this . Cells . Add ( cellKeyValue . Key , cellKeyValue . Value ) ; //cell.Value is the cell incl. Style etc.
2737+ }
2738+ }
2739+
26892740 /// <summary>
26902741 /// Searches for the first occurrence of the value.
26912742 /// </summary>
26922743 /// <param name="searchValue">The value to search for.</param>
2693- /// <returns>The first cell containing the searched value or Null </returns>
2744+ /// <returns>The first cell containing the searched value or null if the value was not found </returns>
26942745 public Cell FirstCellByValue ( object searchValue )
26952746 {
26962747 var cell = this . Cells . FirstOrDefault ( c =>
@@ -2704,12 +2755,11 @@ public Cell FirstCellByValue(object searchValue)
27042755 /// Example: var cell = worksheet.FindCell(c => c.Value?.ToString().Contains("searchValue"));
27052756 /// </summary>
27062757 /// <param name="predicate"></param>
2707- /// <returns>The first cell containing the searched value or Null </returns>
2758+ /// <returns>The first cell containing the searched value or null if the value was not found </returns>
27082759 public Cell FirstOrDefaultCell ( Func < Cell , bool > predicate )
27092760 {
2710- return this . Cells
2711- . FirstOrDefault ( c => predicate ( c . Value ) )
2712- . Value ;
2761+ return this . Cells . Values
2762+ . FirstOrDefault ( c => c != null && ( c . Value == null || predicate ( c ) ) ) ;
27132763 }
27142764
27152765 /// <summary>
@@ -2728,9 +2778,9 @@ public List<Cell> CellsByValue(object searchValue)
27282778 /// <summary>
27292779 /// Replaces all occurrences of 'oldValue' with 'newValue' and returns the number of replacements.
27302780 /// </summary>
2731- /// <param name="oldValue"></param>
2732- /// <param name="newValue"></param>
2733- /// <returns>Count of replaced Cell-Values </returns>
2781+ /// <param name="oldValue">Old value </param>
2782+ /// <param name="newValue">New value that should replace the old one </param>
2783+ /// <returns>Count of replaced Cell values </returns>
27342784 public int ReplaceCellValue ( object oldValue , object newValue )
27352785 {
27362786 int count = 0 ;
0 commit comments