Working over OpenXml, I've came across this article: How to: Merge two adjacent cells in a spreadsheet document (Open XML SDK).
There is a code sample there, that I wanted to refactor. Here is its part:
// Insert a MergeCells object into the specified position.
if (worksheet.Elements<CustomSheetView>().Count() > 0)
{
worksheet.InsertAfter(mergeCells,
worksheet.Elements<CustomSheetView>().First());
}
else if (worksheet.Elements<DataConsolidate>().Count() > 0)
{
worksheet.InsertAfter(mergeCells,
worksheet.Elements<DataConsolidate>().First());
}
else if (worksheet.Elements<SortState>().Count() > 0)
{
worksheet.InsertAfter(mergeCells,
worksheet.Elements<SortState>().First());
}
//...and 5 more
The best thing I managed is an extension method:
public static bool InsertElementAfter<T>(this Worksheet worksheet,
OpenXmlElement element)
where T : OpenXmlElement
{
if (!worksheet.Elements<T>().Any())
return false;
else
{
worksheet.InsertAfter(element, worksheet.Elements<T>().First());
return true;
}
}
But its usage looks as much terrible as the original code:
if (!worksheet.InsertElementAfter<CustomSheetView>(mergeCells))
if (!worksheet.InsertElementAfter<DataConsolidate>(mergeCells))
if (!worksheet.InsertElementAfter<SortState>(mergeCells))
//...and 5 more
If I could somehow declare an array (or something) of type parameters, I would be able to write something like this:
foreach (var T in typeParameterList)
{
if (worksheet.InsertElementAfter<T>(mergeCells))
break;
}
But I do not know any way to do this.
So what are my options?
You could create a fluent API for this. The result could allow code like this:
worksheet.InsertAfter<CustomSheetView>(mergeCells)
.Or<DataConsolidate>()
.Or<SortState>();
There are two advantages to this fluent API:
The implementation of the API would require a class that holds the values and the Or()
method:
public class ChainedElementInserter
{
OpenXmlElement _element;
Worksheet _worksheet;
bool _previousResult;
// ctor that initializes all three fields goes here.
public ChainedElementInserter Or<T>()
where T : OpenXmlElement
{
if (!_previousResult)
_previousResult = _worksheet.InsertElementAfter<T>(_element);
return this;
}
}
The InsertAfter
extension method starts this chain and looks like so:
public static ChainedElementInserter InsertAfter<T>(this Worksheet worksheet,
OpenXmlElement element)
where T : OpenXmlElement
{
return new ChainedElementInserter(
worksheet, element, worksheet.InsertElementAfter<T>(element));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With