Reputation: 51
I need to modify an Excel file with a dropdown list using OpenXML dataValidation.
For some reason, I can create the file with the dropdown but I can't add 1 using Open() method.
The result is an empty excel file without dropdown.
This is the method I used to create the file:
public static void addCreateValidator(string path)
{
using (SpreadsheetDocument myDoc = SpreadsheetDocument.Create(path, SpreadsheetDocumentType.Workbook))
{
WorkbookPart workbookpart = myDoc.AddWorkbookPart();
workbookpart.Workbook = new Workbook();
WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
SheetData sheetData = new SheetData();
worksheetPart.Worksheet = new Worksheet(sheetData);
Sheets sheets = myDoc.WorkbookPart.Workbook.AppendChild(new Sheets());
sheets.AppendChild(new Sheet()
{
Id = myDoc.WorkbookPart.GetIdOfPart(myDoc.WorkbookPart.WorksheetParts.First()),
SheetId = 1,
Name = "Sheet1"
});
DataValidations dataValidations = new DataValidations();
DataValidation dataValidation = new DataValidation()
{
Type = DataValidationValues.List,
AllowBlank = true,
SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A1:A1048576" }
};
Formula1 formula = new Formula1();
formula.Text = "\"FirstChoice,SecondChoice,ThirdChoice\"";
dataValidation.Append(formula);
dataValidations.Append(dataValidation);
worksheetPart.Worksheet.AppendChild(dataValidations);
}
}
This is the method used to modify the file:
public static void addValidation(string filepath)
{
using (SpreadsheetDocument myDoc = SpreadsheetDocument.Open(filepath, true))
{
WorkbookPart wbPart = myDoc.WorkbookPart;
var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
WorksheetPart worksheetPart =
GetWorksheetPartByName(myDoc, "Sheet1");
DataValidations dataValidations = new DataValidations();
DataValidation dataValidation = new DataValidation()
{
Type = DataValidationValues.List,
AllowBlank = true,
SequenceOfReferences = new ListValue<StringValue>() { InnerText = "h1" }
};
Formula1 formula = new Formula1();
formula.Text = "\"FirstChoice,SecondChoice,ThirdChoice\"";
dataValidation.Append(formula);
dataValidations.Append(dataValidation);
worksheetPart.Worksheet.AppendChild(dataValidations);
//worksheetPart.Worksheet.Save();
}
}
Can you see any error or suggest a workaround?
Upvotes: 2
Views: 1456
Reputation: 12815
This is because in the existing file you have some elements that you don't have when you create the file from scratch.
The schema for OpenXml files quite often uses sequences so the order of elements is important. In this case the problem is in your Worksheet
where the schema is:
<xsd:complexType name="CT_Worksheet">
<xsd:sequence>
<xsd:element name="sheetPr" type="CT_SheetPr" minOccurs="0" maxOccurs="1"/>
<xsd:element name="dimension" type="CT_SheetDimension" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sheetViews" type="CT_SheetViews" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sheetFormatPr" type="CT_SheetFormatPr" minOccurs="0" maxOccurs="1"/>
<xsd:element name="cols" type="CT_Cols" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="sheetData" type="CT_SheetData" minOccurs="1" maxOccurs="1"/>
<xsd:element name="sheetCalcPr" type="CT_SheetCalcPr" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sheetProtection" type="CT_SheetProtection" minOccurs="0" maxOccurs="1"/>
<xsd:element name="protectedRanges" type="CT_ProtectedRanges" minOccurs="0" maxOccurs="1"/>
<xsd:element name="scenarios" type="CT_Scenarios" minOccurs="0" maxOccurs="1"/>
<xsd:element name="autoFilter" type="CT_AutoFilter" minOccurs="0" maxOccurs="1"/>
<xsd:element name="sortState" type="CT_SortState" minOccurs="0" maxOccurs="1"/>
<xsd:element name="dataConsolidate" type="CT_DataConsolidate" minOccurs="0" maxOccurs="1"/>
<xsd:element name="customSheetViews" type="CT_CustomSheetViews" minOccurs="0" maxOccurs="1"/>
<xsd:element name="mergeCells" type="CT_MergeCells" minOccurs="0" maxOccurs="1"/>
<xsd:element name="phoneticPr" type="CT_PhoneticPr" minOccurs="0" maxOccurs="1"/>
<xsd:element name="conditionalFormatting" type="CT_ConditionalFormatting" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element name="dataValidations" type="CT_DataValidations" minOccurs="0" maxOccurs="1"/>
<xsd:element name="hyperlinks" type="CT_Hyperlinks" minOccurs="0" maxOccurs="1"/>
<xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/>
<xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/>
<xsd:element name="rowBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/>
<xsd:element name="colBreaks" type="CT_PageBreak" minOccurs="0" maxOccurs="1"/>
<xsd:element name="customProperties" type="CT_CustomProperties" minOccurs="0" maxOccurs="1"/>
<xsd:element name="cellWatches" type="CT_CellWatches" minOccurs="0" maxOccurs="1"/>
<xsd:element name="ignoredErrors" type="CT_IgnoredErrors" minOccurs="0" maxOccurs="1"/>
<xsd:element name="smartTags" type="CT_SmartTags" minOccurs="0" maxOccurs="1"/>
<xsd:element name="drawing" type="CT_Drawing" minOccurs="0" maxOccurs="1"/>
<xsd:element name="drawingHF" type="CT_DrawingHF" minOccurs="0" maxOccurs="1"/>
<xsd:element name="picture" type="CT_SheetBackgroundPicture" minOccurs="0" maxOccurs="1"/>
<xsd:element name="oleObjects" type="CT_OleObjects" minOccurs="0" maxOccurs="1"/>
<xsd:element name="controls" type="CT_Controls" minOccurs="0" maxOccurs="1"/>
<xsd:element name="webPublishItems" type="CT_WebPublishItems" minOccurs="0" maxOccurs="1"/>
<xsd:element name="tableParts" type="CT_TableParts" minOccurs="0" maxOccurs="1"/>
<xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
I suspect the most likely culprit is PageMargins
. DataValidations
must come before the PageMargins
element. You are adding your DataValidations
to the end and by default Excel will write PageMargins
on a new file.
Assuming it is the PageMargins
, the following code should do the trick.
using (SpreadsheetDocument myDoc = SpreadsheetDocument.Open(filepath, true))
{
WorkbookPart wbPart = myDoc.WorkbookPart;
//var sheetData = new DocumentFormat.OpenXml.Spreadsheet.SheetData();
WorksheetPart worksheetPart = GetWorksheetPartByName(myDoc, "Sheet1");
DataValidations dataValidations = new DataValidations();
DataValidation dataValidation = new DataValidation()
{
Type = DataValidationValues.List,
AllowBlank = true,
SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A1:A1048576" }
};
Formula1 formula = new Formula1();
formula.Text = "\"FirstChoice,SecondChoice,ThirdChoice\"";
dataValidation.Append(formula);
dataValidations.Append(dataValidation);
//insert the dataValidations to the correct place
worksheetPart.Worksheet.InsertBefore(dataValidations, worksheetPart.Worksheet.Descendants<PageMargins>().FirstOrDefault());
}
If it's not PageMargins
then it's likely one of the other elements causing the issue. My answer here gives an approach to this problem which is slightly more involved but more reliable.
Upvotes: 1