'Add Dropdown Validation to an entire Excel Column using OpenXML

In Excel, I am able to add validation rules to a range of cells and limit the accepted input to a list of values displayed in a dropdown. This is done using the Data Validation tool, as pictured below:

enter image description here

I have some C# code that generates an excel sheet, and I would like to add this same kind of validation to one of the columns.

Using Microsoft.Office.Interop.Excel, I am able to add this kind of dropdown validation to an entire column:

string flatList = "FirstChoice,SecondChoice,ThirdChoice";

//select the entire first row as the range
Microsoft.Office.Interop.Excel.Range range = worksheet.get_Range("A1").EntireColumn;

//remove any previously existing validation           
range.Validation.Delete();               

//add new validation
range.Validation.Add(
    Microsoft.Office.Interop.Excel.XlDVType.xlValidateList,
    Microsoft.Office.Interop.Excel.XlDVAlertStyle.xlValidAlertInformation,
    Microsoft.Office.Interop.Excel.XlFormatConditionOperator.xlBetween,
    flatList,
    Type.Missing);

range.Validation.IgnoreBlank = true;
range.Validation.InCellDropdown = true;

The problem is, I can't guarantee that my user has Microsoft Office installed. I therefore want to instead use DocumentFormat.OpenXML.

Is it possible to add this same type of dropdown validation using OpenXML?

I've seen some posts using DataValidation, yet have not been able to figure how to get that to work, and if that will solve my problem.



Solution 1:[1]

With a bit more digging, I was able to figure out how to use DataValidation to add dropdown validation to entire column in my Excel sheet using DocumentFormat.OpenXml:

string flatList = "FirstChoice,SecondChoice,ThirdChoice";

DataValidation dataValidation = new DataValidation
{
    Type = DataValidationValues.List,
    AllowBlank = true,

    //Use A:A or A1:A1048576 to select the entire column A
    //1048576 (2^20) is the max row number since Excel 2007.
    SequenceOfReferences = new ListValue<StringValue>() { InnerText = "A:A" },

    //Set the formula to the list of dropdown values. Escape the double quotes.
    Formula1 = new Formula1("\"" + flatList + "\"")
};

//Check if there are any other DataValidations already in the worksheet
DataValidations dvs = worksheet.GetFirstChild<DataValidations>();
if (dvs != null)
{
    //If you already have existing validation for column A, you may need to Remove()
    //or Replace() the current validation to get the new validation to show.          

    //Add the new DataValidation to the list of DataValidations
    dvs.Count = dvs.Count + 1;
    dvs.Append(dataValidation);
}
else
{
    DataValidations newDVs = new DataValidations();
    newDVs.Append(dataValidation);
    newDVs.Count = 1;

    //Append the validation to the DocumentFormat.OpenXml.SpreadSheet.Worksheet variable
    worksheet.Append(newDVs);
}

Solution 2:[2]

You are quite right that you need to use the DataValidation class but you'll also need the DataValidations class too.

A WorkSheet can have zero or one DataValidations which in turn can contain one or many DataValidation's.

The following code will create the Data Validation you are looking for:

using (SpreadsheetDocument myDoc = SpreadsheetDocument.Create(filename, SpreadsheetDocumentType.Workbook))
{
    /*** GENERAL SETUP ***/
    WorkbookPart workbookpart = myDoc.AddWorkbookPart();
    workbookpart.Workbook = new Workbook();
    // Add a WorksheetPart to the WorkbookPart.
    WorksheetPart worksheetPart = workbookpart.AddNewPart<WorksheetPart>();
    SheetData sheetData = new SheetData();
    // Add a WorkbookPart to the document.
    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"
    });

    /***  DATA VALIDATION CODE ***/
    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);
}

Solution 3:[3]

I was able to get manual drop down and I'm making research to get dynamic excel. I was able to figure out how to use DataValidation to add dropdown validation to entire column in my Excel sheet using DocumentFormat.OpenXml.

public class DataInSheet
    {
        public string firstRow { get; set; }

        internal static IEnumerable<object> GetDataOfSheet()
        {
            List<DataInSheet> dataForSheet = new List<DataInSheet>
            {
                new DataInSheet
                {
                    firstRow  = "Sanjay"
                },
                new DataInSheet
                {
                    firstRow  = "Sanjay"
                },
                new DataInSheet
                {
                    firstRow  = "Sanjay"
                },
                new DataInSheet
                {
                    firstRow  = "Sanjay"
                },
                new DataInSheet
                {
                    firstRow  = "Sanjay"
                },
                new DataInSheet
                {
                    firstRow  = "Sanjay"
                },
            };
            return dataForSheet;
        }
    }

    public static void CreateExcelWithDynamicHeader(string fileName, List<string> headerFields, string sheetName, string dropDownItems)
    {
        using (SpreadsheetDocument document = SpreadsheetDocument.Create(fileName, SpreadsheetDocumentType.Workbook))
        {
            WorkbookPart workbookPart = document.AddWorkbookPart();
            workbookPart.Workbook = new Workbook();

            WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
            worksheetPart.Worksheet = new Worksheet(new SheetData());

            WorksheetPart worksheetPart2 = workbookPart.AddNewPart<WorksheetPart>();
            worksheetPart2.Worksheet = new Worksheet(new SheetData());

            Sheets sheets = document.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets());

            //sheets.Append(sheets);

            Worksheet worksheet1 = new Worksheet()
            { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "x14ac" } };
            worksheet1.AddNamespaceDeclaration
            ("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
            worksheet1.AddNamespaceDeclaration
            ("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
            worksheet1.AddNamespaceDeclaration
            ("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");

            Worksheet worksheet2 = new Worksheet()
            { MCAttributes = new MarkupCompatibilityAttributes() { Ignorable = "x14ac" } };
            worksheet2.AddNamespaceDeclaration
            ("r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships");
            worksheet2.AddNamespaceDeclaration
            ("mc", "http://schemas.openxmlformats.org/markup-compatibility/2006");
            worksheet2.AddNamespaceDeclaration
            ("x14ac", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac");


            Sheet sheet = new Sheet() { Id = document.WorkbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = sheetName };

            Sheet sheet1 = new Sheet() { Id = document.WorkbookPart.GetIdOfPart(worksheetPart2), SheetId = 2, Name = dropDownItems };

            sheets.Append(sheet);
            sheets.Append(sheet1);
            //document.WorkbookPart.Workbook.Save();
            SheetData sheetData = new SheetData();
            SheetData sheetData1 = new SheetData();

            double width = 6;
            // Constructing header
            Row headerRow = new Row();
            for (int i = 0; i < headerFields.Count; i++)
            {
                if (width < headerFields[i].Length)
                {
                    width = headerFields[i].Length;
                }

                Columns columns = new Columns();
                columns.Append(new Column() { Min = 1, Max = (UInt32)headerFields.Count, Width = width, CustomWidth = true });

                worksheetPart.Worksheet.Append(columns);
                Cell cell = new Cell();
                cell.DataType = CellValues.String;
                cell.CellValue = new CellValue(headerFields[i]);

                headerRow.AppendChild(cell);
            }
            sheetData.AppendChild(headerRow);
            worksheet1.Append(sheetData);

            int Counter = 1;
            foreach (var value in DataInSheet.GetDataOfSheet())
            {

                Row contentRow = CreateRowValues(Counter, value);
                Counter++;
                sheetData1.AppendChild(contentRow);
            }
            worksheet2.Append(sheetData1);


            DataValidation dataValidation = new DataValidation
            {
                Type = DataValidationValues.List,
                AllowBlank = true,
                SequenceOfReferences = new ListValue<StringValue>() { InnerText = "B1" },
                //Formula1 = new Formula1("'Import Face'!$A$1:$A$6")
                Formula1 = new Formula1("'DropDownDataContainingSheet'!$A:$A")
            };

            DataValidations dataValidations = worksheet1.GetFirstChild<DataValidations>();
            if (dataValidations != null)
            {
                dataValidations.Count = dataValidations.Count + 1;
                dataValidations.Append(dataValidation);
            }
            else
            {
                DataValidations newdataValidations = new DataValidations();
                newdataValidations.Append(dataValidation);
                newdataValidations.Count = 1;
                worksheet1.Append(newdataValidations);
            }
            worksheetPart.Worksheet = worksheet1; ;
            worksheetPart2.Worksheet = worksheet2;
            workbookPart.Workbook.Save();
            document.Close();
        }
    }

    static string[] headerColumns = new string[] { "A", "B", "C", "D" };
    private static Row CreateRowValues(int index, object value)
    {
        Row row = new Row();
        row.RowIndex = (UInt32)index;
        int i = 0;
        foreach (var property in value.GetType().GetProperties())
        {
            Cell cell = new Cell();
            cell.CellReference = headerColumns[i].ToString() + index;
            if (property.PropertyType.ToString()
            .Equals("System.string", StringComparison.InvariantCultureIgnoreCase))
            {

                var result = property.GetValue(value, null);
                if (result == null)
                {
                    result = "";
                }
                cell.DataType = CellValues.String;
                InlineString inlineString = new InlineString();
                Text text = new Text();
                text.Text = result.ToString();
                inlineString.AppendChild(text);
                cell.AppendChild(inlineString);
            }
            if (property.PropertyType.ToString()
            .Equals("System.int32", StringComparison.InvariantCultureIgnoreCase))
            {
                var result = property.GetValue(value, null);
                if (result == null)
                {
                    result = 0;
                }
                CellValue cellValue = new CellValue();
                cellValue.Text = result.ToString();
                cell.AppendChild(cellValue);
            }
            if (property.PropertyType.ToString()
            .Equals("System.boolean", StringComparison.InvariantCultureIgnoreCase))
            {
                var result = property.GetValue(value, null);
                if (result == null)
                {
                    result = "False";
                }
                cell.DataType = CellValues.InlineString;
                InlineString inlineString = new InlineString();
                Text text = new Text();
                text.Text = result.ToString();
                inlineString.AppendChild(text);
                cell.AppendChild(inlineString);
            }

            row.AppendChild(cell);
            i = i + 1;
        }
        return row;
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 petelids
Solution 3 Tot Zam