Scalanie wielu dokumentów word w jeden otwarty Xml
Mam około 10 dokumentów word, które generuję za pomocą open xml i innych rzeczy. Teraz chciałbym utworzyć kolejny dokument word i jeden po drugim chciałbym dołączyć je do tego nowo utworzonego dokumentu. Chciałbym użyć open xml, każda podpowiedź byłaby zauważalna. Poniżej mój kod:
private void CreateSampleWordDocument()
{
//string sourceFile = Path.Combine("D:\\GeneralLetter.dot");
//string destinationFile = Path.Combine("D:\\New.doc");
string sourceFile = Path.Combine("D:\\GeneralWelcomeLetter.docx");
string destinationFile = Path.Combine("D:\\New.docx");
try
{
// Create a copy of the template file and open the copy
//File.Copy(sourceFile, destinationFile, true);
using (WordprocessingDocument document = WordprocessingDocument.Open(destinationFile, true))
{
// Change the document type to Document
document.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document);
//Get the Main Part of the document
MainDocumentPart mainPart = document.MainDocumentPart;
mainPart.Document.Save();
}
}
catch
{
}
}
Update (używając Altchunksa):
using (WordprocessingDocument myDoc = WordprocessingDocument.Open("D:\\Test.docx", true))
{
string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 2) ;
MainDocumentPart mainPart = myDoc.MainDocumentPart;
AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(
AlternativeFormatImportPartType.WordprocessingML, altChunkId);
using (FileStream fileStream = File.Open("D:\\Test1.docx", FileMode.Open))
chunk.FeedData(fileStream);
AltChunk altChunk = new AltChunk();
altChunk.Id = altChunkId;
mainPart.Document
.Body
.InsertAfter(altChunk, mainPart.Document.Body.Elements<Paragraph>().Last());
mainPart.Document.Save();
}
Dlaczego ten kod nadpisuje zawartość ostatniego pliku, gdy używam wielu plików? Update 2:
using (WordprocessingDocument myDoc = WordprocessingDocument.Open("D:\\Test.docx", true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 3);
AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
using (FileStream fileStream = File.Open("d:\\Test1.docx", FileMode.Open))
{
chunk.FeedData(fileStream);
AltChunk altChunk = new AltChunk();
altChunk.Id = altChunkId;
mainPart.Document
.Body
.InsertAfter(altChunk, mainPart.Document.Body
.Elements<Paragraph>().Last());
mainPart.Document.Save();
}
using (FileStream fileStream = File.Open("d:\\Test2.docx", FileMode.Open))
{
chunk.FeedData(fileStream);
AltChunk altChunk = new AltChunk();
altChunk.Id = altChunkId;
mainPart.Document
.Body
.InsertAfter(altChunk, mainPart.Document.Body
.Elements<Paragraph>().Last());
}
using (FileStream fileStream = File.Open("d:\\Test3.docx", FileMode.Open))
{
chunk.FeedData(fileStream);
AltChunk altChunk = new AltChunk();
altChunk.Id = altChunkId;
mainPart.Document
.Body
.InsertAfter(altChunk, mainPart.Document.Body
.Elements<Paragraph>().Last());
}
}
Ten kod jest dołączanie danych Test2 dwa razy, w miejsce danych Test1, jak również. Czyli dostaję:
Test
Test2
Test2
Zamiast:
Test
Test1
Test2
3 answers
Używając tylko OPENXML SDK, możesz użyć AltChunk
element do scalania wielu dokumentów w jeden.
Ten link the-easy-way-to-assembly-multiple-word-documents i ten Jak używać altChunk do składania dokumentów dostarczają kilku przykładów.
EDIT 1
Na podstawie Twojego kodu, który używa altchunk
w zaktualizowanym pytaniu (Aktualizacja#1), oto VB.Net kod, który przetestowałem i działa jak czar dla ja:
Using myDoc = DocumentFormat.OpenXml.Packaging.WordprocessingDocument.Open("D:\\Test.docx", True)
Dim altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 2)
Dim mainPart = myDoc.MainDocumentPart
Dim chunk = mainPart.AddAlternativeFormatImportPart(
DocumentFormat.OpenXml.Packaging.AlternativeFormatImportPartType.WordprocessingML, altChunkId)
Using fileStream As IO.FileStream = IO.File.Open("D:\\Test1.docx", IO.FileMode.Open)
chunk.FeedData(fileStream)
End Using
Dim altChunk = New DocumentFormat.OpenXml.Wordprocessing.AltChunk()
altChunk.Id = altChunkId
mainPart.Document.Body.InsertAfter(altChunk, mainPart.Document.Body.Elements(Of DocumentFormat.OpenXml.Wordprocessing.Paragraph).Last())
mainPart.Document.Save()
End Using
EDIT 2
Drugi numer (Aktualizacja#2)
Kod ten dołącza dane Test2 dwa razy, zamiast danych Test1 jako cóż.
Jest związane z altchunkid
.
Dla każdego dokumentu, który chcesz scalić w głównym dokumencie, musisz:
- dodaj
AlternativeFormatImportPart
wmainDocumentPart
zId
który musi być wyjątkowy. ten element zawiera wstawione dane - Dodaj do ciała
Altchunk
element, w którym ustawiaszid
, aby odwoływał się do poprzedniegoAlternativeFormatImportPart
.
W kodzie używasz tego samego Id dla wszystkich AltChunks
. Dlatego często widzisz ten sam tekst.
Nie jestem pewien, czy altchunkid będzie unikalny z Twoim kodem: string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString().Substring(0, 2);
Jeśli nie musisz ustawiać konkretnej wartości, zalecam, aby nie ustawiać jawnie AltChunkId
Po dodaniu AlternativeFormatImportPart
. Zamiast tego otrzymujesz jeden wygenerowany przez SDK w następujący sposób:
VB.Net
Dim chunk As AlternativeFormatImportPart = mainPart.AddAlternativeFormatImportPart(DocumentFormat.OpenXml.Packaging.AlternativeFormatImportPartType.WordprocessingML)
Dim altchunkid As String = mainPart.GetIdOfPart(chunk)
C#
AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(DocumentFormat.OpenXml.Packaging.AlternativeFormatImportPartType.WordprocessingML);
string altchunkid = mainPart.GetIdOfPart(chunk);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-22 19:02:00
Istnieje ładny API wrapper (Document Builder 2.2) wokół open xml specjalnie zaprojektowany do łączenia dokumentów, z elastycznością wyboru akapitów do scalania itp. Możesz go pobrać z tutaj (aktualizacja: przeniesiona na github).
Dokumentacja i screeny jak z niej korzystać znajdują się tutaj .
Update: Code Sample
var sources = new List<Source>();
//Document Streams (File Streams) of the documents to be merged.
foreach (var stream in documentstreams)
{
var tempms = new MemoryStream();
stream.CopyTo(tempms);
sources.Add(new Source(new WmlDocument(stream.Length.ToString(), tempms), true));
}
var mergedDoc = DocumentBuilder.BuildDocument(sources);
mergedDoc.SaveAs(@"C:\TargetFilePath");
Typy Source
i WmlDocument
pochodzą z API Kreatora dokumentów.
Możesz nawet dodać ścieżki plików bezpośrednio jeśli wybierzesz jako:
sources.Add(new Source(new WmlDocument(@"C:\FileToBeMerged1.docx"));
sources.Add(new Source(new WmlDocument(@"C:\FileToBeMerged2.docx"));
Znalazłem to ładne porównanie pomiędzy AltChunk
i Document Builder
podejść do scalania dokumentów - pomocne w wyborze na podstawie własnych wymagań.
Możesz również użyć biblioteki DocX do scalania dokumentów, ale do scalania dokumentów wolę program Document Builder.
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-28 09:13:18
Łatwy w użyciu w C#:
using System;
using System.IO;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace WordMergeProject
{
public class Program
{
private static void Main(string[] args)
{
byte[] word1 = File.ReadAllBytes(@"..\..\word1.docx");
byte[] word2 = File.ReadAllBytes(@"..\..\word2.docx");
byte[] result = Merge(word1, word2);
File.WriteAllBytes(@"..\..\word3.docx", result);
}
private static byte[] Merge(byte[] dest, byte[] src)
{
string altChunkId = "AltChunkId" + DateTime.Now.Ticks.ToString();
var memoryStreamDest = new MemoryStream();
memoryStreamDest.Write(dest, 0, dest.Length);
memoryStreamDest.Seek(0, SeekOrigin.Begin);
var memoryStreamSrc = new MemoryStream(src);
using (WordprocessingDocument doc = WordprocessingDocument.Open(memoryStreamDest, true))
{
MainDocumentPart mainPart = doc.MainDocumentPart;
AlternativeFormatImportPart altPart =
mainPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.WordprocessingML, altChunkId);
altPart.FeedData(memoryStreamSrc);
var altChunk = new AltChunk();
altChunk.Id = altChunkId;
OpenXmlElement lastElem = mainPart.Document.Body.Elements<AltChunk>().LastOrDefault();
if(lastElem == null)
{
lastElem = mainPart.Document.Body.Elements<Paragraph>().Last();
}
//Page Brake einfügen
Paragraph pageBreakP = new Paragraph();
Run pageBreakR = new Run();
Break pageBreakBr = new Break() { Type = BreakValues.Page };
pageBreakP.Append(pageBreakR);
pageBreakR.Append(pageBreakBr);
return memoryStreamDest.ToArray();
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-14 11:03:30