我是一家大型公司的实习生,他的任务是完成一个以前的实习生项目,该项目显然在某些方面有效,但现在已经破了。程序的作用是,从文档中获取大量文本和图像,并将它们插入到模板文档中。问题是,大约一半的图像没有形成关系,我得到红色X“图像无法显示”空框。我一直在使用生产力工具进行一些挖掘,我发现有一些重复的ID,以及相当多的不存在的关系,虽然看着他的代码我不知道是什么原因可能导致。以下是他复制图像的两种方法:
internal static void CopyImages(OpenXmlElement oldTable, OpenXmlElement newTable,
WordprocessingDocument testData, WordprocessingDocument testReport)
{
List<Blip> sourceBlips = DocumentHelper.GetAllBlips(oldTable);
List<Blip> targetBlips = DocumentHelper.GetAllBlips(newTable);
foreach (Blip sourceBlip in sourceBlips)
{
foreach (Blip targetBlip in targetBlips)
{
if (targetBlip.Embed.Value == sourceBlip.Embed.Value)
{
if (testData.MainDocumentPart.GetPartById(sourceBlip.Embed.Value) is ImagePart imagePart)
{
ImagePart newImagePart = testReport.MainDocumentPart.AddPart(imagePart);
targetBlip.Embed.Value = testReport.MainDocumentPart.GetIdOfPart(newImagePart);
break;
}
}
}
}
}
internal static void CopyEmbeddedVisioImages(OpenXmlElement oldTable, OpenXmlElement newTable,
WordprocessingDocument testData, WordprocessingDocument testReport)
{
List<EmbeddedObject> sourceObjects = oldTable.Descendants<EmbeddedObject>().ToList();
List<EmbeddedObject> targetObjects = newTable.Descendants<EmbeddedObject>().ToList();
foreach (EmbeddedObject targetobj in targetObjects)
{
foreach (EmbeddedObject sourceObj in sourceObjects)
{
if (testData.MainDocumentPart.GetPartById(sourceObj.Descendants<ImageData>()
.FirstOrDefault().RelationshipId) is ImagePart oldImagePart)
{
ImagePart newImagePart = testReport.MainDocumentPart.AddPart(oldImagePart);
targetobj.Descendants<ImageData>().FirstOrDefault().RelationshipId =
testReport.MainDocumentPart.GetIdOfPart(newImagePart);
}
if (testData.MainDocumentPart.GetPartById(sourceObj.Descendants<OleObject>()
.FirstOrDefault().Id) is OpenXmlPart openXmlPart)
{
EmbeddedObjectPart newEmbeddedObj = (EmbeddedObjectPart)testReport.MainDocumentPart.AddPart(openXmlPart);
targetobj.Descendants<OleObject>().FirstOrDefault().Id =
testReport.MainDocumentPart.GetIdOfPart(newEmbeddedObj);
}
}
}
}
我试过在文档上调用Save()和Close()。我甚至试过调用Dispose()。 using(WordprocessingDocument foo = WordprocessingDocument.Open(bar, false){}
似乎也没有帮助。我现在不太担心重复的ID,但我不知道为什么只有一些关系正在形成,而其他关系不是。这是一个庞大的项目,因此浏览其中一些可能非常棘手。
编辑:可能还值得一提的是,图像在某一点停止形成关系。这不是随机的。大约有2/3的路没有图像可以工作。
这是更新的方法集
internal static void CopyImages(OpenXmlElement oldTable, OpenXmlElement newTable,
WordprocessingDocument testData, WordprocessingDocument testReport)
{
List<Blip> sourceBlips = DocumentHelper.GetAllBlips(oldTable);
List<Blip> targetBlips = DocumentHelper.GetAllBlips(newTable);
foreach (Blip sourceBlip in sourceBlips)
{
foreach (Blip targetBlip in targetBlips)
{
if (targetBlip.Embed.Value == sourceBlip.Embed.Value)
{
if (testData.MainDocumentPart.GetPartById(sourceBlip.Embed.Value) is ImagePart imagePart)
{
//ImagePart newImagePart = testReport.MainDocumentPart.AddPart(imagePart);
ImagePart newImagePart = testReport.MainDocumentPart.AddImagePart(imagePart.ContentType);
newImagePart.FeedData(imagePart.GetStream(FileMode.Open, FileAccess.Read));
targetBlip.Embed.Value = testReport.MainDocumentPart.GetIdOfPart(newImagePart);
break;
}
}
}
}
}
internal static void CopyEmbeddedVisioImages(OpenXmlElement oldTable, OpenXmlElement newTable,
WordprocessingDocument testData, WordprocessingDocument testReport)
{
List<EmbeddedObject> sourceObjects = oldTable.Descendants<EmbeddedObject>().ToList();
List<EmbeddedObject> targetObjects = newTable.Descendants<EmbeddedObject>().ToList();
foreach (EmbeddedObject targetobj in targetObjects)
{
foreach (EmbeddedObject sourceObj in sourceObjects)
{
if (testData.MainDocumentPart.GetPartById(sourceObj.Descendants<ImageData>()
.FirstOrDefault().RelationshipId) is ImagePart oldImagePart)
{
//ImagePart newImagePart = testReport.MainDocumentPart.AddPart(oldImagePart);
ImagePart newImagePart = testReport.MainDocumentPart.AddImagePart(oldImagePart.ContentType);
newImagePart.FeedData(oldImagePart.GetStream(FileMode.Open, FileAccess.Read));
targetobj.Descendants<ImageData>().FirstOrDefault().RelationshipId =
testReport.MainDocumentPart.GetIdOfPart(newImagePart);
}
if (testData.MainDocumentPart.GetPartById(sourceObj.Descendants<OleObject>()
.FirstOrDefault().Id) is OpenXmlPart openXmlPart)
{
EmbeddedObjectPart newEmbeddedObj = (EmbeddedObjectPart)testReport.MainDocumentPart.AddPart(openXmlPart);
targetobj.Descendants<OleObject>().FirstOrDefault().Id =
testReport.MainDocumentPart.GetIdOfPart(newEmbeddedObj);
}
}
}
}
以下是我的调查结果的最新消息。
targetBlip.Embed.Value != sourceBlip.Embed.Value
在大多数情况下或者可能是别的什么?答案 0 :(得分:2)
源文档中的图像无法原样添加到目标文档中; 图像在其父文档中具有唯一的ID /编号,如果已存在具有相同ID的图像,则该图像可能与目标文档冲突。 替换以下行
ImagePart newImagePart = testReport.MainDocumentPart.AddPart(imagePart);
以下一个。这里嵌入了一个全新的图像文件,并获得了一个新的id。
ImagePart newImagePart = testReport.MainDocumentPart.AddImagePart(oldImagePart.ContentType);
newImagePart.FeedData(oldImagePart.GetStream(FileMode.Open, FileAccess.Read));
目标文档中的ID是唯一的,这一点非常重要。 我分享了一些(旧的())代码片段,关于我如何处理将图像从一个文档合并到另一个文档。 (这是一个更完整/复杂实现的片段,其中检测到重复图像并防止多次插入。)
首先迭代源文档中的所有绘图,并在此源文档中构建这些绘图的列表及其原始ID。然后将所有图像插入目标文档中;这样做时,目标文档中的新ID将映射到每个项目。
源文档中的每个图形都使用目标文档中的id进行更新;该列表包含原始源和新目标ID。 (这听起来很奇怪,但对我而言,这只是给出了预期的结果。)
只有在图像合并完成后,内容(段落和表格)才会合并到目标文档中,其中包括添加这些项目的克隆。
public class DocumentMerger
{
private readonly WordprocessingDocument _targetDocument;
public DocumentMerger(WordprocessingDocument targetDocument)
{
this._targetDocument = targetDocument;
}
public void Merge(WordprocessingDocument sourceDocument)
{
ImagesMerger imagesMerger = new ImagesMerger(this._targetDocument);
this._imagesMerger.Merge(sourceDocument);
// Merge the content; paragraphs and tables.
this._targetDocumentPart.Document.Save();
}
}
public class ImageInfo
{
private String _id;
private ImagePart _image;
private readonly String _originalId;
private ImageInfo(ImagePart image, String id)
{
this._id = id;
this._image = image;
this._originalId = id;
}
public String Id
{
get { return this._id; }
}
public ImagePart Image
{
get { return this._image; }
}
public String OriginalId
{
get { return this._originalId; }
}
public static ImageInfo Create(MainDocumentPart documentPart, ImagePart image)
{
String id = documentPart.GetIdOfPart(image);
ImageInfo r = new ImageInfo(image, id);
return r;
}
public void Reparent(MainDocumentPart documentPart)
{
ImagePart newImage = documentPart.AddImagePart(this._image.ContentType);
newImage.FeedData(this._image.GetStream(FileMode.Open, FileAccess.Read));
String newId = documentPart.GetIdOfPart(newImage);
this._id = newId;
this._image = newImage;
}
}
public class ImagesMerger
{
private readonly IList<ImageInfo> _imageInfosOfTheTargetDocument = new List<ImageInfo>();
private readonly MainDocumentPart _targetDocumentPart;
public ImagesMerger(WordprocessingDocument targetDocument)
{
this._targetDocumentPart = targetDocument.MainDocumentPart;
}
public void Merge(WordprocessingDocument sourceDocument)
{
MainDocumentPart sourceDocumentPart = sourceDocument.MainDocumentPart;
IList<ImageInfo> imageInfosOfTheSourceDocument = this.getImageInfos(sourceDocumentPart);
if (0 == imageInfosOfTheSourceDocument.Count) { return; }
this.addTheImagesToTheTargetDocument(imageInfosOfTheSourceDocument);
this.rereferenceTheImagesToTheirCorrespondingImageParts(sourceDocumentPart, imageInfosOfTheSourceDocument);
}
private void addTheImagesToTheTargetDocument(IList<ImageInfo> imageInfosOfTheSourceDocument)
{
for (Int32 i = 0, j = imageInfosOfTheSourceDocument.Count; i < j; i++)
{
imageInfoOfTheSourceDocument.Reparent(this._targetDocumentPart);
this._imageInfosOfTheTargetDocument.Add(imageInfoOfTheSourceDocument);
}
}
private IList<ImageInfo> getImageInfos(MainDocumentPart documentPart)
{
List<ImageInfo> r = new List<ImageInfo>();
foreach (ImagePart image in documentPart.ImageParts)
{
ImageInfo imageInfo = ImageInfo.Create(documentPart, image);
r.Add(imageInfo);
}
return r;
}
private void rereferenceTheImagesToTheirCorrespondingImageParts(MainDocumentPart sourceDocumentPart, IList<ImageInfo> imageInfosOfTheSourceDocument)
{
IEnumerable<Drawing> images = sourceDocumentPart.Document.Body.Descendants<Drawing>();
foreach (Drawing image in images)
{
Blip blip = image.Inline.Graphic.GraphicData.Descendants<Blip>().FirstOrDefault();
String originalId = blip.Embed.Value;
ImageInfo imageInfo = imageInfosOfTheSourceDocument.FirstOrDefault(o => o.OriginalId._Equals(originalId));
blip.Embed.Value = imageInfo.Id;
}
}
}