OpenXml изображения не существует - PullRequest
0 голосов
/ 22 мая 2018

Я - стажер в крупной компании, которой поручено работать над проектом предыдущего стажера, который, очевидно, работал в какой-то момент, но теперь он не работает.Программа делает то, что она берет кучу текста и изображений из документа и вставляет их в шаблон документа.Проблема в том, что около половины изображений не образуют отношений, и я получаю красный X пустой значок «Изображение не может быть отображено».Я немного покопался в инструменте повышения производительности и обнаружил, что есть пара дублирующих идентификаторов, а также довольно много несуществующих отношений, хотя, глядя на его код, я не уверен, что может быть причиной этого.,Вот два его метода копирования изображений:

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){} похоже тоже не помогает.Пока я не слишком беспокоюсь о дублирующих идентификаторах, но я понятия не имею, почему формируются только некоторые отношения, а другие нет.Это масштабный проект, поэтому навигация по нему может быть довольно сложной.

Редактировать: Вероятно, стоит упомянуть, что изображения перестают формировать отношения в определенной точке.Это не случайно.Примерно на 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);
                }
            }
        }
    }

Вот обновление моих выводов.

  • Всего документов всего 25.
  • targetBlip.Embed.Value != sourceBlip.Embed.Value в большинстве случаев или, может быть, что-то еще?
  • Элементы, содержащие изображения, клонированы из источникадокумент, а затем сохраняется в целевой документ.
  • Все элементы читаются.Таблицы, содержащие изображения с разорванными связями, существуют и заполняются другим содержимым, поэтому не то, чтобы в них отсутствовали эти элементы.
  • Дублирующие идентификаторы связаны с целевым документом, содержащим пару изображений для начала, поэтому при копированииповерх других изображений некоторые из этих идентификаторов дублируются.Сейчас это не мое дело.

1 Ответ

0 голосов
/ 22 мая 2018

Изображения из исходного документа не могут быть добавлены как есть в целевой документ;изображение имеет уникальный идентификатор / номер в родительском документе, и это может конфликтовать с целевым документом, если оно уже существует с тем же идентификатором.Замените следующую строку

ImagePart newImagePart = testReport.MainDocumentPart.AddPart(imagePart);

на следующую.Здесь внедряется совершенно новый файл изображения и ему присваивается новый идентификатор.

ImagePart newImagePart = testReport.MainDocumentPart.AddImagePart(oldImagePart.ContentType);
newImagePart.FeedData(oldImagePart.GetStream(FileMode.Open, FileAccess.Read));

Важно, чтобы идентификаторы в целевом документе были уникальными.Я поделюсь некоторыми (старыми (er)) фрагментами кода о том, как я справился с объединением изображений из одного документа в другой.(Это фрагмент более полной / сложной реализации, в которой повторяющиеся изображения обнаруживаются и не могут быть вставлены более одного раза.)

Он начинается с перебора всех чертежей в исходном документе и построения спискаони вместе с их оригинальным идентификатором, как в этом исходном документе.Затем все изображения вставляются в целевой документ;при этом новый идентификатор, как в целевом документе, сопоставляется с каждым элементом.

Каждый чертеж в исходном документе обновляется с идентификатором, как в целевом документе;список содержит как исходные, так и новые целевые идентификаторы.(Это звучит странно, но для меня в тот момент только это дало ожидаемый результат.)

Только после завершения слияния изображения содержимое (абзацы и таблицы) объединяются в целевой документ, который состоит издобавление клонов этих предметов.

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