Ejemplo n.º 1
0
        public void CreateMSWordDocument(Guid identifier)
        {
            var    myResume    = _resumeManagerRepository.Get(m => m.Guid.Equals(identifier)).First().Resume;
            string projPath    = HttpContext.Current.Server.MapPath("~/Content/");
            string outFilePath = Path.Combine(projPath, "doc", myResume.ResumeManager.Link);

            byte[] templateBytes = System.IO.File.ReadAllBytes(projPath + "MSWordTemplates\\template4.dotx");

            using (MemoryStream templateStream = new MemoryStream())
            {
                templateStream.Write(templateBytes, 0, (int)templateBytes.Length);

                using (WordprocessingDocument doc = WordprocessingDocument.Open(templateStream, true))
                {
                    doc.ChangeDocumentType(WordprocessingDocumentType.Document);
                    var mainPart = doc.MainDocumentPart;

                    // Get the Document Settings Part
                    DocumentSettingsPart documentSettingPart1 = mainPart.DocumentSettingsPart;

                    // Create a new attachedTemplate and specify a relationship ID
                    AttachedTemplate attachedTemplate1 = new AttachedTemplate()
                    {
                        Id = "relationId1"
                    };

                    // Append the attached template to the DocumentSettingsPart
                    documentSettingPart1.Settings.Append(attachedTemplate1);

                    // Add an ExternalRelationShip of type AttachedTemplate.
                    // Specify the path of template and the relationship ID
                    documentSettingPart1.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate", new Uri(projPath + "MSWordTemplates\\template4.dotx", UriKind.Absolute), "relationId1");

                    string fullname = string.Format("{0} {1}", myResume.FirstName, myResume.LastName);
                    SetCCText(mainPart, "FullName", fullname);

                    SetCCText(mainPart, "Goal", myResume.Goal);
                    SetCCText(mainPart, "Location", myResume.CurrentLocation);

                    string email = myResume.Contacts.First(c => c.ContactTitle.Title.Equals("EMail")).Data;
                    SetCCText(mainPart, "Email", email);

                    string phone = myResume.Contacts.First(c => c.ContactTitle.Title.Equals("Phone")).Data;
                    SetCCText(mainPart, "Phone", phone);

                    RemoveCCChild(mainPart, "OtherContacts");
                    foreach (var contact in myResume.Contacts.Where(c => !c.ContactTitle.Title.Equals("EMail") && !c.ContactTitle.Title.Equals("Phone")))
                    {
                        AppendCCText(mainPart, "OtherContacts", string.Format("{0}: {1}", contact.ContactTitle.Title, contact.Data));
                    }

                    // ОБРАЗОВАНИЕ
                    if (myResume.Education.Count > 0)
                    {
                        SdtBlock contentControl = mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Section_Education").Single();
                        Table    theTable       = contentControl.Descendants <Table>().Single();
                        TableRow defaultRow     = theTable.Elements <TableRow>().Last();

                        foreach (var institution in myResume.Education)
                        {
                            TableRow rowCopy = (TableRow)defaultRow.CloneNode(true);

                            // период учебы
                            var periodRun = rowCopy.Descendants <TableCell>().ElementAt(0).GetFirstChild <Paragraph>().GetFirstChild <Run>();
                            periodRun.GetFirstChild <Text>().Text = string.Format("{0} –", institution.From.Format());
                            periodRun.Append(new Break());
                            periodRun.Append(new Text(institution.To.Format()));

                            // описание уч. заведениия:
                            // название и город
                            TableCell secondColumn = rowCopy.Descendants <TableCell>().ElementAt(1);
                            SetCCText(secondColumn, "InstitutionName", string.Format("{0}, г. {1}", institution.Name, institution.City));

                            // кафедра
                            if (string.IsNullOrEmpty(institution.Department))
                            {
                                secondColumn.Descendants <SdtRun>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "InstitutionDepartment").Single().Parent.Remove();
                            }
                            else
                            {
                                SetCCText(secondColumn, "InstitutionDepartment", institution.Department);
                            }

                            // специальность
                            SetCCText(secondColumn, "InstitutionSpeciality", institution.Specialty);
                            secondColumn.Elements <Paragraph>().Last().Append(new Run(new Break()));

                            theTable.AppendChild(rowCopy);
                        }
                        theTable.RemoveChild(defaultRow);
                    }
                    else
                    {
                        mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Section_Education").Single().Remove();
                    }

                    // ОПЫТ РАБОТЫ
                    if (myResume.WorkExp.Count > 0)
                    {
                        SdtBlock contentControl = mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Section_Experience").Single();
                        Table    theTable       = contentControl.Descendants <Table>().Single();
                        TableRow defaultRow     = theTable.Elements <TableRow>().Last();

                        foreach (var workPlace in myResume.WorkExp)
                        {
                            TableRow rowCopy = (TableRow)defaultRow.CloneNode(true);

                            // период в который работали
                            var periodRun = rowCopy.Descendants <TableCell>().ElementAt(0).GetFirstChild <Paragraph>().GetFirstChild <Run>();
                            periodRun.GetFirstChild <Text>().Text = string.Format("{0} –", workPlace.From.Format());
                            periodRun.Append(new Break());
                            periodRun.Append(new Text(workPlace.To.Format()));

                            // описание работы:
                            // название работы и город
                            TableCell secondColumn = rowCopy.Descendants <TableCell>().ElementAt(1);
                            SetCCText(secondColumn, "WorkplaceName", string.Format("{0}, г. {1}", workPlace.Name, workPlace.City));

                            // должность
                            SetCCText(secondColumn, "WorkplacePosition", workPlace.Position);

                            // обязанности
                            if (workPlace.Duties.Count > 0)
                            {
                                RemoveCCChild(secondColumn, "WorkplaceDuties");
                                foreach (var duty in workPlace.Duties)
                                {
                                    AppendCCText(secondColumn, "WorkplaceDuties", string.Format("– {0}", duty.Name));
                                }
                            }
                            else
                            {
                                secondColumn.Descendants <SdtRun>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "WorkplaceDuties").Single().Parent.Remove();
                            }

                            //secondColumn.Elements<Paragraph>().Last().Append(new Run(new Break()));

                            theTable.AppendChild(rowCopy);
                        }
                        theTable.RemoveChild(defaultRow);
                    }
                    else
                    {
                        mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Section_Experience").Single().Remove();
                    }


                    // СЕРТИФИКАТЫ
                    if (myResume.CertificatesAndTrainings.Count > 0)
                    {
                        RemoveCCChild(mainPart, "Certificates");
                        foreach (var certificate in myResume.CertificatesAndTrainings)
                        {
                            AppendCCText(mainPart, "Certificates", string.Format("{0} – {1}{2}", certificate.Date.Year, certificate.Name, certificate.Location != null ? string.Format(", г. {0}", certificate.Location) : ""));
                        }
                    }
                    else
                    {
                        RemoveCC(mainPart, "Section_Certificates");
                    }

                    // ЯЗЫКИ
                    if (myResume.Languages.Count > 0)
                    {
                        SdtBlock        contentControl = mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Languages").Single();
                        SdtContentBlock contentRun     = contentControl.GetFirstChild <SdtContentBlock>();
                        Paragraph       defaultLi      = contentRun.GetFirstChild <Paragraph>();

                        foreach (var language in myResume.Languages)
                        {
                            Paragraph copy = (Paragraph)defaultLi.CloneNode(true);
                            copy.Descendants <Text>().Where(t => t.Text == "lang").Single().Text  = language.Name;
                            copy.Descendants <Text>().Where(t => t.Text == "level").Single().Text = language.Level;
                            contentRun.Append(copy);
                        }
                        contentRun.RemoveChild(defaultLi);
                    }
                    else
                    {
                        RemoveCC(mainPart, "Section_Languages");
                    }

                    // ЛИЧНЫЕ КАЧЕСТВА
                    if (myResume.PersonalQualities.Count > 0)
                    {
                        SdtBlock        contentControl = mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "PersonalQualities").Single();
                        SdtContentBlock contentRun     = contentControl.GetFirstChild <SdtContentBlock>();
                        Paragraph       defaultLi      = contentRun.GetFirstChild <Paragraph>();

                        foreach (var quality in myResume.PersonalQualities)
                        {
                            Paragraph copy = (Paragraph)defaultLi.CloneNode(true);
                            copy.Descendants <Text>().Where(t => t.Text == "quality").Single().Text = quality.Name;
                            contentRun.Append(copy);
                        }
                        contentRun.RemoveChild(defaultLi);
                    }
                    else
                    {
                        mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Section_PersonalQualities").Single().Remove();
                    }

                    // НАВЫКИ
                    if (myResume.Skills.Count > 0)
                    {
                        SdtBlock        contentControl = mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Skills").Single();
                        SdtContentBlock contentRun     = contentControl.GetFirstChild <SdtContentBlock>();
                        Paragraph       defaultLi      = contentRun.GetFirstChild <Paragraph>();

                        foreach (var skill in myResume.Skills)
                        {
                            Paragraph copy = (Paragraph)defaultLi.CloneNode(true);
                            copy.Descendants <Text>().Where(t => t.Text == "skill").Single().Text = skill.Name;
                            contentRun.Append(copy);
                        }
                        contentRun.RemoveChild(defaultLi);
                    }
                    else
                    {
                        mainPart.Document.Body.Descendants <SdtBlock>().Where(r => r.SdtProperties.GetFirstChild <Tag>().Val == "Section_Skills").Single().Remove();
                    }

                    mainPart.Document.Save();
                }
                File.WriteAllBytes(outFilePath, templateStream.ToArray());
            }
        }
        public static void Fill(OpenXmlElement docNode, XmlElement macroListXml, WordprocessingDocument wdDoc)
        {
            /* Форматированный текст для встроенных элементов */
            IEnumerable <Paragraph> paragraphs = docNode.Elements <Paragraph>();

            foreach (Paragraph paragraph in paragraphs)
            {
                IEnumerable <SdtRun> sdtRuns = paragraph.Elements <SdtRun>();
                foreach (SdtRun sdtRun in sdtRuns)
                {
                    // Из SdtProperties взять Tag для идентификации Content Control
                    SdtProperties sdtProperties = sdtRun.GetFirstChild <SdtProperties>();
                    Tag           tag           = sdtProperties.GetFirstChild <Tag>();

                    // Найти в macroListXml Node макропеременной
                    String macroVarValue = FindMacroVar(macroListXml, tag.Val);

                    if (macroVarValue != null)
                    {
                        // Сохранить старый стиль Run
                        SdtContentRun  sdtContentRun = sdtRun.GetFirstChild <SdtContentRun>();
                        OpenXmlElement oldRunProps   = sdtContentRun.GetFirstChild <Run>().GetFirstChild <RunProperties>().CloneNode(true);

                        // Очистить Node Content Control
                        sdtContentRun.RemoveAllChildren();

                        // Создать новую Run Node
                        Run newRun = sdtContentRun.AppendChild(new Run());
                        // Вернуть старый стиль
                        newRun.AppendChild(oldRunProps);

                        // Вставить текст (без переносов строк!!!)
                        newRun.AppendChild(new Text(macroVarValue));
                    }
                }
            }

            /* Получить остальные Content Control */
            IEnumerable <SdtBlock> sdtBlocks = docNode.Elements <SdtBlock>();

            foreach (SdtBlock sdtBlock in sdtBlocks)
            {
                // Получить параметры(SdtProperties) Content Control
                SdtProperties sdtProperties = sdtBlock.GetFirstChild <SdtProperties>();

                // Получить Tag для идентификации Content Control
                Tag tag = sdtProperties.GetFirstChild <Tag>();

                // Получить значение макроперенной из macroListXml
                Console.WriteLine("Tag: " + tag.Val);
                String macroVarValue = FindMacroVar(macroListXml, tag.Val);

                // Если макропеременная есть в MacroListXml
                if (macroVarValue != null)
                {
                    Console.WriteLine("Value: " + macroVarValue);
                    // Получить блок содержимого Content Control
                    SdtContentBlock sdtContentBlock = sdtBlock.GetFirstChild <SdtContentBlock>();

                    /* Форматированный текст для абзацев */
                    if (sdtProperties.GetFirstChild <SdtPlaceholder>() != null && sdtContentBlock.GetFirstChild <Paragraph>() != null)
                    {
                        // Сохранить старый стиль параграфа
                        ParagraphProperties oldParagraphProperties = sdtContentBlock.GetFirstChild <Paragraph>().GetFirstChild <ParagraphProperties>().CloneNode(true) as ParagraphProperties;
                        String oldParagraphPropertiesXml           = oldParagraphProperties.InnerXml;

                        // Очистить ноду с контентом
                        sdtContentBlock.RemoveAllChildren();

                        InsertText(macroVarValue, oldParagraphPropertiesXml, sdtContentBlock);
                    }

                    /* Таблицы */
                    if (sdtProperties.GetFirstChild <SdtPlaceholder>() != null && sdtContentBlock.GetFirstChild <Table>() != null)
                    {
                        // Получить ноду таблицы
                        Table table = sdtContentBlock.GetFirstChild <Table>();

                        // Получить все строки таблицы
                        IEnumerable <TableRow> tableRows = table.Elements <TableRow>();

                        // Получить вторую строку из таблицы
                        TableRow tableRow     = tableRows.ElementAt(1) as TableRow;
                        Type     tableRowType = tableRow.GetType();

                        // Получить все стили столбцов
                        List <String> paragraphCellStyles       = new List <string>();
                        IEnumerable <OpenXmlElement> tableCells = tableRow.Elements <TableCell>();
                        foreach (OpenXmlElement tableCell in tableCells)
                        {
                            String paragraphCellStyleXml = tableCell.GetFirstChild <Paragraph>().GetFirstChild <ParagraphProperties>().InnerXml;
                            paragraphCellStyles.Add(paragraphCellStyleXml);
                        }

                        // Удалить все строки, после первой
                        while (tableRows.Count <TableRow>() > 1)
                        {
                            TableRow lastTableRows = tableRows.Last <TableRow>();
                            lastTableRows.Remove();
                        }

                        // Удалить последний элемент, если это не TableRow
                        OpenXmlElement lastNode = table.LastChild;
                        if (lastNode.GetType() != tableRowType)
                        {
                            lastNode.Remove();
                        }

                        string[] rowDelimiters    = new string[] { "|||" };
                        string[] columnDelimiters = new string[] { "^^^" };

                        // Получить массив строк из макропеременной
                        String[] rowsXml = macroVarValue.Split(rowDelimiters, StringSplitOptions.None);
                        int      i       = 0;
                        while (i < rowsXml.Length)
                        {
                            // Получить строку
                            String rowXml = rowsXml[i];

                            // Добавить ноду строки таблицы
                            TableRow newTableRow = table.AppendChild(new TableRow());

                            // Получить из строки массив ячеек
                            String[] cellsXml = rowXml.Split(columnDelimiters, StringSplitOptions.None);

                            int j = 0;
                            while (j < cellsXml.Length)
                            {
                                // Получить ячейку
                                String cellXml = cellsXml[j];

                                // Убрать символ CRLF в конце строки
                                cellXml = cellXml.TrimEnd(new char[] { '\n', '\r' });

                                // Добавить ноду ячейку в строку таблицы
                                TableCell newTableCell = newTableRow.AppendChild(new TableCell());

                                // Вставить текст
                                InsertText(cellXml, paragraphCellStyles[j], newTableCell);

                                j++;
                            }

                            i++;
                        }
                    }

                    /* Картинки */
                    if (sdtProperties.GetFirstChild <SdtContentPicture>() != null)
                    {
                        // Получить путь к файлу
                        String imageFilePath = macroVarValue;

                        // Получить расширение файла
                        String        extension = System.IO.Path.GetExtension(imageFilePath).ToLower();
                        ImagePartType imagePartType;
                        switch (extension)
                        {
                        case "jpeg":
                            imagePartType = ImagePartType.Jpeg;
                            break;

                        case "jpg":
                            imagePartType = ImagePartType.Jpeg;
                            break;

                        case "png":
                            imagePartType = ImagePartType.Png;
                            break;

                        case "bmp":
                            imagePartType = ImagePartType.Bmp;
                            break;

                        case "gif":
                            imagePartType = ImagePartType.Gif;
                            break;

                        default:
                            imagePartType = ImagePartType.Jpeg;
                            break;
                        }
                        ;

                        // Добавить ImagePart в документ
                        ImagePart imagePart = wdDoc.MainDocumentPart.AddImagePart(imagePartType);

                        // Получить картинку
                        using (FileStream stream = new FileStream(imageFilePath, FileMode.Open))
                        {
                            imagePart.FeedData(stream);
                        }

                        // Вычислить width и height
                        Bitmap    img         = new Bitmap(imageFilePath);
                        var       widthPx     = img.Width;
                        var       heightPx    = img.Height;
                        var       horzRezDpi  = img.HorizontalResolution;
                        var       vertRezDpi  = img.VerticalResolution;
                        const int emusPerInch = 914400;
                        const int emusPerCm   = 360000;
                        var       widthEmus   = (long)(widthPx / horzRezDpi * emusPerInch);
                        var       heightEmus  = (long)(heightPx / vertRezDpi * emusPerInch);

                        // Получить ID ImagePart
                        string relationShipId = wdDoc.MainDocumentPart.GetIdOfPart(imagePart);

                        Paragraph   paragraph   = sdtContentBlock.GetFirstChild <Paragraph>();
                        Run         run         = paragraph.GetFirstChild <Run>();
                        Drawing     drawing     = run.GetFirstChild <Drawing>();
                        Inline      inline      = drawing.GetFirstChild <Inline>();
                        Graphic     graphic     = inline.GetFirstChild <Graphic>();
                        GraphicData graphicData = graphic.GetFirstChild <GraphicData>();
                        Picture     pic         = graphicData.GetFirstChild <Picture>();
                        BlipFill    blipFill    = pic.GetFirstChild <BlipFill>();
                        Blip        blip        = blipFill.GetFirstChild <Blip>();

                        string prefix       = "r";
                        string localName    = "embed";
                        string namespaceUri = @"http://schemas.openxmlformats.org/officeDocument/2006/relationships";

                        OpenXmlAttribute oldEmbedAttribute = blip.GetAttribute("embed", namespaceUri);

                        IList <OpenXmlAttribute> attributes = blip.GetAttributes();

                        if (oldEmbedAttribute != null)
                        {
                            attributes.Remove(oldEmbedAttribute);
                        }

                        // Удалить хз что, выявлено практическим путем
                        blipFill.RemoveAllChildren <SourceRectangle>();

                        // Установить новую картинку
                        blip.SetAttribute(new OpenXmlAttribute(prefix, localName, namespaceUri, relationShipId));
                        blip.SetAttribute(new OpenXmlAttribute("cstate", "", "print"));

                        // Подогнать размеры
                        Extent extent = inline.GetFirstChild <Extent>();

                        OpenXmlAttribute oldCxExtent = extent.GetAttribute("cx", "");
                        if (oldCxExtent != null)
                        {
                            var maxWidthEmus = long.Parse(oldCxExtent.Value);
                            if (widthEmus > maxWidthEmus)
                            {
                                var ratio = (heightEmus * 1.0m) / widthEmus;
                                widthEmus  = maxWidthEmus;
                                heightEmus = (long)(widthEmus * ratio);
                            }

                            extent.GetAttributes().Remove(oldCxExtent);
                        }

                        OpenXmlAttribute oldCyExtent = extent.GetAttribute("cy", "");
                        if (oldCyExtent != null)
                        {
                            extent.GetAttributes().Remove(oldCyExtent);
                        }

                        extent.SetAttribute(new OpenXmlAttribute("cx", "", widthEmus.ToString()));
                        extent.SetAttribute(new OpenXmlAttribute("cy", "", heightEmus.ToString()));

                        ShapeProperties shapeProperties = pic.GetFirstChild <ShapeProperties>();
                        Transform2D     transform2D     = shapeProperties.GetFirstChild <Transform2D>();
                        Extents         extents         = transform2D.GetFirstChild <Extents>();

                        OpenXmlAttribute oldCxExtents = extents.GetAttribute("cx", "");
                        if (oldCxExtents != null)
                        {
                            extents.GetAttributes().Remove(oldCxExtents);
                        }

                        OpenXmlAttribute oldCyExtents = extents.GetAttribute("cy", "");
                        if (oldCyExtents != null)
                        {
                            extents.GetAttributes().Remove(oldCyExtents);
                        }

                        extents.SetAttribute(new OpenXmlAttribute("cx", "", widthEmus.ToString()));
                        extents.SetAttribute(new OpenXmlAttribute("cy", "", heightEmus.ToString()));

                        // Удалить placeholder
                        ShowingPlaceholder showingPlaceholder = sdtProperties.GetFirstChild <ShowingPlaceholder>();
                        if (showingPlaceholder != null)
                        {
                            sdtProperties.RemoveChild <ShowingPlaceholder>(showingPlaceholder);
                        }
                    }

                    /* Повторяющийся раздел */
                    if (sdtProperties.GetFirstChild <SdtRepeatedSection>() != null)
                    {
                        // Представить repeatedSection как новый xml документ (сделать корнем)
                        XmlDocument repeatedSectionXml = new XmlDocument();
                        repeatedSectionXml.LoadXml(macroVarValue);

                        // Получить корневой элемент repeatedSection
                        XmlElement rootRepeatedSectionXml = repeatedSectionXml.DocumentElement;

                        // Получить количество repeatedSectionItem
                        XmlNodeList repeatedSectionItems = rootRepeatedSectionXml.SelectNodes("repeatedSectionItem");
                        int         repeatedItemCount    = repeatedSectionItems.Count;

                        Console.WriteLine("Количество repeatedSectionItem: " + repeatedItemCount);

                        /* Блок клонирования ноды повтор. раздела до нужного количества */
                        for (int i = 0; i < repeatedItemCount; i++)
                        {
                            XmlElement macroListRepeatedSectionItem = rootRepeatedSectionXml.SelectSingleNode(String.Format(@"repeatedSectionItem[@id=""{0}""]", i)) as XmlElement;
                            Console.WriteLine("Item " + i + ": " + macroListRepeatedSectionItem.OuterXml);

                            SdtContentBlock sdtContentBlockRepeatedSectionItem = sdtContentBlock.Elements <SdtBlock>().Last <SdtBlock>().GetFirstChild <SdtContentBlock>();

                            Fill(sdtContentBlockRepeatedSectionItem, macroListRepeatedSectionItem, wdDoc);

                            if (i + 1 < repeatedItemCount)
                            {
                                SdtBlock clonedRepeatedSectionItem = sdtContentBlock.GetFirstChild <SdtBlock>().Clone() as SdtBlock;
                                sdtContentBlock.AppendChild <SdtBlock>(clonedRepeatedSectionItem);
                            }
                        }
                        /**/

                        //Fill(sdtContentBlock, macroListRepeatedSection, wdDoc);
                    }
                }

                Console.WriteLine();
            }
        }