Ошибка OpenXml Table "<p> элементы требуются перед каждым </tc>" - PullRequest
10 голосов
/ 28 ноября 2011

Я создал шаблон Word, который затем обрабатываю с помощью OpenXML SDK, чтобы заменить часть содержимого документа данными из запроса к базе данных.

Шаблон состоит из некоторого основного текста с простым текстомКонтент управления вводится в тех местах, где я хочу заменить текст.Затем я использую текст в этих элементах управления в качестве ключа для поиска значений замены.В большинстве случаев это работает нормально (я просто обновляю свойство Text объекта Text).

В одном случае я заменяю текст таблицей.В этом случае я создаю таблицу в коде, а затем заменяю содержимое объекта SdtContentRun (родительского объекта объекта Run, который, в свою очередь, является родительским объектом объекта Text) новым объектом Table ...

var sdtContentRunElements =
  from sdtContentRun in this.Document.MainDocumentPart.RootElement.Descendants<SdtContentRun>()
  select sdtContentRun;

sdtContentRunElements.ForEach(sdtContentRunElement => {

  Run firstRunElement = sdtContentRunElement.Descendants<Run>().FirstOrDefault();
  if (firstRunElement != null) {

    Text firstTextElement = firstRunElement.Descendants<Text>().FirstOrDefault();
    if (firstTextElement != null) {

      switch (firstTextElement.Text) {

        case TableBookmark:

          Table advisoryTable = new Table(...); // See below
          OpenXmlElement parent = firstRunElement.Parent;
          parent.RemoveAllChildren();
          parent.Append(advisoryTable);
          break;

        case ContractorItemAdvisoriesLetter.ContractorCodeBookmark:

          firstTextElement.Text = @"New text";
          break;

      }
    }
  }
}

}

Это приводит к следующему XML (взятому из инструмента повышения производительности Open XML SDK 2.0 для Microsoft Office) ...

<w:sdtContent xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:tbl>
    <w:tr>
      <w:tc>
        <w:p>
          <w:r>
            <w:t>Lorem ipsum dolor sit amet</w:t>
          </w:r>
        </w:p>
      </w:tc>
    </w:tr>
  </w:tbl>
</w:sdtContent>

(Некоторые изсодержимое таблицы было удалено, так как я чувствовал, что это просто затуманивает проблему)

Когда я пытаюсь открыть документ в Word, я получаю сообщение об ошибке.Сообщается об ошибке ...

Произошло неоднозначное сопоставление ячеек.Возможен пропущенный элемент абзаца.

элементов требуется перед каждым

Вероятно, стоит упомянуть, что при просмотре проводника документов в инструменте повышения производительности Open XML SDK 2.0 для Microsoft Office элемент w: tbl (ивсе содержащиеся в нем элементы) распознаются как OpenXmlUnknownElement, а не как Table объекты.Я не знаю, имеет ли это отношение или является ли это причудой инструмента SDK.

Очевидно, я что-то упустил.Насколько я могу судить по определению класса Table , совершенно правильно размещать aw: tbl внутри aw: sdtContent (если я не читаю это неправильно), так что теперь я в растерянности относительно того, чтопроблема может быть.Также вы получите очень мало результатов, если вы воспользуетесь Google "Таблица" и "OpenXmlUnknownElement", и ни один из результатов не будет связан с моей проблемой.указать, что проблема на самом деле заключается во встраивании другой таблицы в одну из ячеек таблицы, добавляемой выше.Новый объект Table добавляется непосредственно в объект TableCell, который, опять же, в соответствии с документацией для таблицы, упомянутой выше, должен быть приемлемым ...

Table advisoryTable = new Table();

advisories.ForEach(advisory => {

    advisoryTable.Append(new TableRow(new TableCell(new Paragraph(new Run(new Text(advisory.NoteText))))));

    advisory.ItemAdvisories.ForEach(itemAdvisory => {

        Item item = itemAdvisory.Item;

        Table itemTable = new Table();
        itemTable.Append(new TableRow[] {

            new TableRow(new TableCell[] {
                new TableCell(new Paragraph(new Run(new Text(string.Format(@"Item {0}", item.Sequence)))))
            })

        });

        advisoryTable.Append(new TableRow(new TableCell(itemTable)));

    });

});

В результате ...

<w:tbl xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:tr>
    <w:tc>
      <w:p>
        <w:r>
          <w:t>Lorem ipsum dolor sit amet</w:t>
        </w:r>
      </w:p>
    </w:tc>
  </w:tr>
  <w:tr>
    <w:tc>
      <w:tbl>
        <w:tr>
          <w:tc>
            <w:p>
              <w:r>
                <w:t>Item 1</w:t>
              </w:r>
            </w:p>
          </w:tc>
        </w:tr>
      </w:tbl>
    </w:tc>
  </w:tr>
</w:tbl>

Я попытался добавить Paragraph между TableCell и встроенной таблицей, но это просто приводит к новой ошибке, на этот раз «неопределенная ошибка».

1 Ответ

16 голосов
/ 29 ноября 2011

Сортировка. Исходное сообщение об ошибке не могло быть более ясным!

Последний дочерний элемент ячейки таблицы должен быть абзацем. Просто добавив пустой абзац после того, как встроенная таблица решила проблему ...

advisoryTable.Append(new TableRow(new TableCell(itemTable, new Paragraph())));

В конце концов я обнаружил это, создав документ в Word-2010, который состоял из таблицы в таблице, и затем посмотрел полученный XML-код в том же инструменте повышения производительности Open XML SDK 2.0 для Microsoft Office, который использовался выше.

...