Skip to content

Commit 78d7156

Browse files
authored
Merge pull request #10 from fahadadeel/main
Enhanced Range Class and Worksheet Functionalities for Advanced Spreadsheet Operations
2 parents 7c3800e + 91fe429 commit 78d7156

File tree

2 files changed

+212
-0
lines changed

2 files changed

+212
-0
lines changed

FileFormat.Cells/Range.cs

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace FileFormat.Cells
8+
{
9+
public class Range
10+
{
11+
private readonly Worksheet _worksheet;
12+
13+
public uint StartRowIndex { get; }
14+
public uint StartColumnIndex { get; }
15+
public uint EndRowIndex { get; }
16+
public uint EndColumnIndex { get; }
17+
18+
// Returns the count of columns in the range
19+
public uint ColumnCount
20+
{
21+
get { return EndColumnIndex - StartColumnIndex + 1; }
22+
}
23+
24+
// Returns the count of rows in the range
25+
public uint RowCount
26+
{
27+
get { return EndRowIndex - StartRowIndex + 1; }
28+
}
29+
30+
31+
public Range(Worksheet worksheet, uint startRowIndex, uint startColumnIndex, uint endRowIndex, uint endColumnIndex)
32+
{
33+
_worksheet = worksheet ?? throw new ArgumentNullException(nameof(worksheet));
34+
StartRowIndex = startRowIndex;
35+
StartColumnIndex = startColumnIndex;
36+
EndRowIndex = endRowIndex;
37+
EndColumnIndex = endColumnIndex;
38+
}
39+
40+
public void SetValue(string value)
41+
{
42+
for (uint row = StartRowIndex; row <= EndRowIndex; row++)
43+
{
44+
for (uint column = StartColumnIndex; column <= EndColumnIndex; column++)
45+
{
46+
var cellReference = $"{ColumnIndexToLetter(column)}{row}";
47+
var cell = _worksheet.GetCell(cellReference);
48+
cell.PutValue(value);
49+
}
50+
}
51+
}
52+
53+
public void ClearCells()
54+
{
55+
for (uint row = StartRowIndex; row <= EndRowIndex; row++)
56+
{
57+
for (uint column = StartColumnIndex; column <= EndColumnIndex; column++)
58+
{
59+
var cellReference = $"{ColumnIndexToLetter(column)}{row}";
60+
var cell = _worksheet.GetCell(cellReference);
61+
if (cell != null)
62+
{
63+
cell.PutValue(string.Empty); // Clearing the value
64+
cell.ApplyStyle(0); // Resetting the style if needed
65+
}
66+
}
67+
}
68+
}
69+
70+
public void MergeCells()
71+
{
72+
string startCellReference = $"{ColumnIndexToLetter(StartColumnIndex)}{StartRowIndex}";
73+
string endCellReference = $"{ColumnIndexToLetter(EndColumnIndex)}{EndRowIndex}";
74+
75+
_worksheet.MergeCells(startCellReference, endCellReference);
76+
}
77+
78+
79+
public void AddDropdownListValidation(string[] options)
80+
{
81+
82+
83+
for (uint row = StartRowIndex; row <= EndRowIndex; row++)
84+
{
85+
for (uint column = StartColumnIndex; column <= EndColumnIndex; column++)
86+
{
87+
var cellReference = $"{ColumnIndexToLetter(column)}{row}";
88+
_worksheet.AddDropdownListValidation(cellReference, options);
89+
}
90+
}
91+
}
92+
93+
94+
95+
private static string ColumnIndexToLetter(uint columnIndex)
96+
{
97+
string columnLetter = string.Empty;
98+
while (columnIndex > 0)
99+
{
100+
columnIndex--;
101+
columnLetter = (char)('A' + columnIndex % 26) + columnLetter;
102+
columnIndex /= 26;
103+
}
104+
return columnLetter;
105+
}
106+
}
107+
108+
109+
}

FileFormat.Cells/Worksheet.cs

+103
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using DocumentFormat.OpenXml.Packaging;
66
using DocumentFormat.OpenXml.Spreadsheet;
77

8+
89
namespace FileFormat.Cells
910
{
1011
/// <summary>
@@ -15,6 +16,10 @@ public sealed class Worksheet
1516
private WorksheetPart _worksheetPart;
1617
private SheetData _sheetData;
1718

19+
public const double DefaultColumnWidth = 8.43; // Default width in character units
20+
public const double DefaultRowHeight = 15.0; // Default height in points
21+
22+
1823
/// <summary>
1924
/// Gets the indexer for cells within the worksheet.
2025
/// </summary>
@@ -171,6 +176,51 @@ public void SetColumnWidth(string columnName, double width)
171176
}
172177
}
173178

179+
public double GetColumnWidth(uint columnIndex)
180+
{
181+
// Access the Columns collection
182+
var columns = _worksheetPart.Worksheet.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.Columns>();
183+
if (columns != null)
184+
{
185+
foreach (var column in columns.Elements<Column>())
186+
{
187+
188+
// Explicitly cast Min and Max to uint and check for null
189+
uint min = column.Min.HasValue ? column.Min.Value : uint.MinValue;
190+
uint max = column.Max.HasValue ? column.Max.Value : uint.MaxValue;
191+
192+
if (columnIndex >= min && columnIndex <= max)
193+
{
194+
// Also check if Width is set
195+
return column.Width.HasValue ? column.Width.Value : DefaultColumnWidth;
196+
}
197+
}
198+
}
199+
200+
return DefaultColumnWidth;
201+
}
202+
203+
public double GetRowHeight(uint rowIndex)
204+
{
205+
// Assuming _worksheetPart is the OpenXML WorksheetPart
206+
var rows = _worksheetPart.Worksheet.GetFirstChild<DocumentFormat.OpenXml.Spreadsheet.SheetData>().Elements<Row>();
207+
208+
foreach (var row in rows)
209+
{
210+
// Check if this is the row we are looking for
211+
if (row.RowIndex.Value == rowIndex)
212+
{
213+
// If Height is set, return it, otherwise return default height
214+
return row.Height.HasValue ? row.Height.Value : DefaultRowHeight;
215+
}
216+
}
217+
218+
return DefaultRowHeight; // Return default height if no specific height is set
219+
}
220+
221+
222+
223+
174224
/// <summary>
175225
/// Protects the worksheet with the specified password.
176226
/// </summary>
@@ -382,6 +432,59 @@ public int GetSheetIndex()
382432
// If you specifically need the index, you may need to implement a different approach.
383433
return int.Parse(sheet.SheetId);
384434
}
435+
436+
public Range GetRange(uint startRowIndex, uint startColumnIndex, uint endRowIndex, uint endColumnIndex)
437+
{
438+
return new Range(this, startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
439+
}
440+
441+
public Range GetRange(string startCellReference, string endCellReference)
442+
{
443+
var startCellParts = ParseCellReference(startCellReference);
444+
var endCellParts = ParseCellReference(endCellReference);
445+
return GetRange(startCellParts.row, startCellParts.column, endCellParts.row, endCellParts.column);
446+
}
447+
448+
public void AddDropdownListValidation(string cellReference, string[] options)
449+
{
450+
// Convert options array into a comma-separated string
451+
string formula = string.Join(",", options);
452+
453+
// Create the data validation object
454+
DataValidation dataValidation = new DataValidation
455+
{
456+
Type = DataValidationValues.List,
457+
ShowDropDown = true,
458+
ShowErrorMessage = true,
459+
ErrorTitle = "Invalid input",
460+
Error = "The value entered is not in the list.",
461+
Formula1 = new Formula1("\"" + formula + "\""), // The formula is enclosed in quotes
462+
SequenceOfReferences = new ListValue<StringValue> { InnerText = cellReference }
463+
};
464+
465+
// Add the data validation to the worksheet
466+
var dataValidations = _worksheetPart.Worksheet.GetFirstChild<DataValidations>();
467+
if (dataValidations == null)
468+
{
469+
dataValidations = new DataValidations();
470+
_worksheetPart.Worksheet.AppendChild(dataValidations);
471+
}
472+
473+
dataValidations.AppendChild(dataValidation);
474+
}
475+
476+
477+
private (uint row, uint column) ParseCellReference(string cellReference)
478+
{
479+
var match = Regex.Match(cellReference, @"([A-Z]+)(\d+)");
480+
if (!match.Success)
481+
throw new FormatException("Invalid cell reference format.");
482+
483+
uint row = uint.Parse(match.Groups[2].Value);
484+
uint column = (uint)ColumnLetterToIndex(match.Groups[1].Value);
485+
486+
return (row, column);
487+
}
385488
}
386489

387490
public class CellIndexer

0 commit comments

Comments
 (0)