contact_name과 같은 특정 변수를 사용하도록 사용자가 디자인 한 단일 페이지 입력 docx 템플릿 파일이 있습니다. OpenXml SDK + Open-Xml-PowerTools를 사용하여 처리하는 동안이 템플릿을 기반으로 한 docx 파일의 인스턴스를 많이 만들고 실제 값을 변수로 대체합니다. 결국 하나의 docx 출력이 필요하므로 Open-Xml-PowerTools DocumentBuilder를 사용하여 하나의 docx로 병합합니다.docx 파일을 하나에 병합하고 번호 목록 서식을 유지합니다.
사용자가 번호 매기기 목록을 템플릿에 넣을 때까지 작동하는 것처럼 보입니다. 내 원래의 문제는 번호가 매겨진 목록이 문서 인스턴스의 병합 이후 번호 매김을 계속했습니다. 즉, 문서의 모든 항목이 동일한 목록 ID를 참조한다고 생각하여 목록의 두 번째 페이지의 번호가 1-10 대신 11-20이었습니다.
문서 본문에서 고유 한 num ID를 지정하여 문제를 해결할 수 있었지만 목록의 형식이 첫 번째 페이지를 넘어 손실되었습니다. 첫 번째 페이지에서 번호가 매겨진 목록 항목은 들여 쓰기되어 있지만 두 번째 이후에는 번호가 매겨지지 않은 목록처럼 페이지에 남아 있지 않습니다. 스타일 매기기 및 번호 매기기 섹션을 업데이트하여 이러한 새 num id를 일치시켜야하지만이 작업을 수행 할 수없는 것 같습니다.
나는이 문제를 ericwhite.com의 포럼에 올렸지 만 최신 문제 (http://ericwhite.com/blog/forums/topic/list-numbering-on-merged-docs/)에 관해서들은 적이 없습니다.
이 문제를 해결하기위한 최근의 시도로 OpenXml-Power-Tools에서 예외가 발생하므로 새 목록 ID로 일부 섹션을 업데이트하지 않을 것으로 생각됩니다. 누구든지이 작업을 수행하는 방법을 알고 있습니까? 다음은 예외를 따르는 코드입니다.
public bool Merge(List<InterchangeableWordProcessingDocument> inputFiles, string outputFilePath)
{
if (inputFiles == null)
{
logger.LogDebug("No files to merge.");
return true;
}
try
{
List<OpenXmlPowerTools.Source> sources = new List<OpenXmlPowerTools.Source>();
int highestListNumbering = 0;
int highestAbstractListNumbering = 0;
foreach (var inputFile in inputFiles)
{
//Sometimes merge puts start of next page onto end of previous one so prevent
//Seems to cause extra blank page when there are labels so don't do on labels pages
if (inputFile.DocType == DocType.Letter)
{
using (var wordDoc = inputFile.GetAsWordProcessingDocument())
{
var para = wordDoc.MainDocumentPart.Document.Body.ChildElements.First<Paragraph>();
if (para.ParagraphProperties == null)
{
para.ParagraphProperties = new ParagraphProperties();
}
para.ParagraphProperties.PageBreakBefore = new PageBreakBefore();
//http://ericwhite.com/blog/forums/topic/list-numbering-on-merged-docs/
//Numberings should be unique to each page otherwise they continue from the previous
//Keep track of how many we have so we can add on to always have a unique number
var numIds = wordDoc.MainDocumentPart.Document.Body.Descendants<NumberingId>().ToList();
logger.LogDebug("Found " + numIds.Count + " num ids.");
foreach (var numId in numIds)
numId.Val += highestListNumbering;
var styleNumIds = wordDoc.MainDocumentPart.StyleDefinitionsPart.RootElement.Descendants<NumberingId>().ToList();
if (wordDoc.MainDocumentPart.StyleDefinitionsPart != null)
{
logger.LogDebug("Found " + styleNumIds.Count + " stlye num ids.");
foreach (var styleNumId in styleNumIds)
styleNumId.Val += highestListNumbering;
}
if (wordDoc.MainDocumentPart.NumberingDefinitionsPart != null)
{
var numberingNumIds = wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.Descendants<NumberingInstance>().ToList();
logger.LogDebug("Found " + numberingNumIds.Count + " numbering num ids.");
foreach (var numberingNumId in numberingNumIds)
{
numberingNumId.NumberID += highestListNumbering;
numberingNumId.AbstractNumId.Val += highestAbstractListNumbering;
}
var abstractNumberingNumIds = wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.Descendants<AbstractNumId>().ToList();
logger.LogDebug("Found " + abstractNumberingNumIds.Count + " abstract num ids." + wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.XName.LocalName);
foreach (var abstractNumberingNumId in abstractNumberingNumIds)
abstractNumberingNumId.Val += highestAbstractListNumbering;
//Keep the max nums up to date
if (abstractNumberingNumIds.Count > 0)
highestAbstractListNumbering = Math.Max(highestAbstractListNumbering, abstractNumberingNumIds.Max(ln => (ln.Val.HasValue ? ln.Val.Value : 0)));
}
if (numIds.Count > 0)
highestListNumbering = Math.Max(highestListNumbering, numIds.Max(ln => (ln.Val.HasValue ? ln.Val.Value : 0)));
wordDoc.MainDocumentPart.Document.Save();
}
}
sources.Add(new OpenXmlPowerTools.Source(inputFile.GetAsWmlDocument(), true));
}
DocumentBuilder.BuildDocument(sources, outputFilePath);
return true;
}
catch (SystemException ex)
{
logger.LogError("Error occured while generating bereavement letters. ", ex);
return false;
}
finally
{
foreach (var inputFile in inputFiles)
{
inputFile.Dispose();
}
}
}
예외 :
각 패스 동안 동일한 AbstractNumId 참조 값을 두 번 업데이트하고 마치System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at OpenXmlPowerTools.DocumentBuilder.CopyNumbering(WordprocessingDocument sourceDocument, WordprocessingDocument newDocument, IEnumerable1 newContent, List1 images)
at OpenXmlPowerTools.DocumentBuilder.AppendDocument(WordprocessingDocument sourceDocument, WordprocessingDocument newDocument, List1 newContent, Boolean keepSection, String insertId, List1 images)
at OpenXmlPowerTools.DocumentBuilder.BuildDocument(List`1 sources, WordprocessingDocument output)
at OpenXmlPowerTools.DocumentBuilder.BuildDocument(List`1 sources, String fileName)
at BereavementMailing.TemplateEngine.Merge(List`1 inputFiles, String outputFilePath) in C:\caw\Underdog\Apps\Services\BereavementMailingEngine\BM_RequestProcessor\TemplateEngine.cs:line 508