Нужна помощь в добавлении OpenXML dataValidation в существующий файл Excel - PullRequest
1 голос
/ 11 марта 2019

Мне нужно изменить файл Excel с помощью раскрывающегося списка с помощью OpenXML dataValidation.

По какой-то причине я могу создать файл с раскрывающимся списком, но не могу добавить 1 с помощью метода Open ().

В результате получается пустой файл Excel без раскрывающегося списка.

Это метод, который я использовал для создания файла:

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);
    }
}

Этот метод используется для изменения файла:

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();
        }


    }

Можете ли вы увидеть ошибку или предложить обходной путь?

1 Ответ

0 голосов
/ 12 марта 2019

Это потому, что в существующем файле есть некоторые элементы, которых нет при создании файла с нуля.

Схема для файлов OpenXml довольно часто использует последовательности, поэтому важен порядок элементов. В этом случае проблема в вашем Worksheet, где схема:

<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>

Я подозреваю, что наиболее вероятный виновник - PageMargins. DataValidations должен предшествовать перед элементом PageMargins. Вы добавляете DataValidations в конец, и по умолчанию Excel напишет PageMargins в новом файле.

Предполагая, что это PageMargins, следующий код должен помочь.

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());
}

Если это не PageMargins, то, скорее всего, это один из других элементов, вызывающих проблему. Мой ответ здесь дает подход к этой проблеме, который несколько сложнее, но более надежен.

...