从DOCX提取表 [英] Extract table from DOCX

查看:72
本文介绍了从DOCX提取表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用OpenXML(C#)解析* .docx文档时遇到一个问题.

I have one problem with parsing *.docx document with OpenXML (C#).

所以,这是我的步骤:
1.加载* .docx文档
2.接收段落列表
3.在每个段落中查找文本,图像和表格元素
4.为每个文本和图像元素创建html标签
5.将输出另存为* .html文件

So, here's my steps:
1. Load *.docx document
2. Recieve list of paragraphs
3. In each paragraph look for text,image and table elements
4. For each text and image element create html tags
5. Save output as *.html file

我已经找到了如何在文档中找到图像文件并提取它. 现在,只需走一个步骤-查找表在文本(段落)中的位置.

I've found out how to locate image file in document and extract it. Now there's one step to go - find where is table position in text (paragraph).

如果有人知道如何使用OpenXML在* .docx文档中找到表,请提供帮助. 谢谢.

If any one know how to locate table in *.docx document using OpenXML please help. Thanks.

其他: 好吧,也许我不清楚我的意思. 如果我们获得段落的内容,则可以找到诸如文本块,图片等的对象. 因此,如果段落包含的Run包含Picture,则意味着在Word文档中的该位置放置了图像.

Additional: Ok, may be I'm not clear explain what i mean. If we get content of paragraph, you can find chield objects as textblocks, pictures and so on. So, if paragraph contains Run that contains Picture it means that in this place in Word document placed image.

我的功能示例:

public static string ParseDocxDocument(string pathToFile)
    {
        StringBuilder result = new StringBuilder();
        WordprocessingDocument wordProcessingDoc = WordprocessingDocument.Open(pathToFile, true);
        List<ImagePart> imgPart = wordProcessingDoc.MainDocumentPart.ImageParts.ToList();
        IEnumerable<Paragraph> paragraphElement = wordProcessingDoc.MainDocumentPart.Document.Descendants<Paragraph>();
        int imgCounter = 0;


        foreach (Paragraph par in paragraphElement)
        {

                //Add new paragraph tag
                result.Append("<div style=\"width:100%; text-align:");

                //Append anchor style
                if (par.ParagraphProperties != null && par.ParagraphProperties.Justification != null)
                    switch (par.ParagraphProperties.Justification.Val.Value)
                    {
                        case JustificationValues.Left:
                            result.Append("left;");
                            break;
                        case JustificationValues.Center:
                            result.Append("center;");
                            break;
                        case JustificationValues.Both:
                            result.Append("justify;");
                            break;
                        case JustificationValues.Right:
                        default:
                            result.Append("right;");
                            break;
                    }
                else
                    result.Append("left;");

                //Append text decoration style
                if (par.ParagraphProperties != null && par.ParagraphProperties.ParagraphMarkRunProperties != null && par.ParagraphProperties.ParagraphMarkRunProperties.HasChildren)
                    foreach (OpenXmlElement chield in par.ParagraphProperties.ParagraphMarkRunProperties.ChildElements)
                    {
                        switch (chield.GetType().Name)
                        {
                            case "Bold":
                                result.Append("font-weight:bold;");
                                break;
                            case "Underline":
                                result.Append("text-decoration:underline;");
                                break;
                            case "Italic":
                                result.Append("font-style:italic;");
                                break;
                            case "FontSize":
                                result.Append("font-size:" + ((FontSize)chield).Val.Value + "px;");
                                break;
                            default: break;
                        }
                    }

                result.Append("\">");

                //Add image tag
                IEnumerable<Run> runs = par.Descendants<Run>();
                foreach (Run run in runs)
                {
                    if (run.HasChildren)
                    {
                        foreach (OpenXmlElement chield in run.ChildElements.Where(o => o.GetType().Name == "Picture"))
                        {
                            result.Append(string.Format("<img style=\"{1}\" src=\"data:image/jpeg;base64,{0}\" />", GetBase64Image(imgPart[imgCounter].GetStream()),
                                           ((DocumentFormat.OpenXml.Vml.Shape)chield.ChildElements.Where(o => o.GetType().Name == "Shape").FirstOrDefault()).Style
                                ));
                            imgCounter++;
                        }
                    }
                }

                //Append inner text
                IEnumerable<Text> textElement = par.Descendants<Text>();
                if (par.Descendants<Text>().Count() == 0)
                    result.Append("<br />");

                foreach (Text t in textElement)
                {
                    result.Append(t.Text);
                }


                result.Append("</div>");
                result.Append(Environment.NewLine);

        }

        wordProcessingDoc.Close();

        return result.ToString();
    }

现在我想在文本中指定表格位置(在Word中显示).

Now I whant to specify table place in text (as it appear in Word).

最终:

好吧,每个人,我都知道了.在我的示例函数中,一个大错误.我列举了文件正文的段落元素.表与段落处于同一级别,因此函数将忽略表.因此,我们需要枚举文档正文的元素.

Ok, everyone, I've found out. In my sample function one big mistake. I'm enumerate Paragraph elements of document Body. Tables are at same level as Paragraph, so function ignore tables. So we need to enumerate Elements of document Body.

这是我的测试功能,可以从docx生成正确的HTML(这只是测试代码,因此不干净)

Here's my test function to generate correct HTML from docx (it's just test code, so it's not clean)

public static string ParseDocxDocument(string pathToFile)
    {
        StringBuilder result = new StringBuilder();
        WordprocessingDocument wordProcessingDoc = WordprocessingDocument.Open(pathToFile, true);
        List<ImagePart> imgPart = wordProcessingDoc.MainDocumentPart.ImageParts.ToList();
        List<string> tableCellContent = new List<string>();
        IEnumerable<Paragraph> paragraphElement = wordProcessingDoc.MainDocumentPart.Document.Descendants<Paragraph>();
        int imgCounter = 0;

        foreach (OpenXmlElement section in wordProcessingDoc.MainDocumentPart.Document.Body.Elements<OpenXmlElement>())
        {
            if(section.GetType().Name == "Paragraph")
            {
              Paragraph par = (Paragraph)section;
                //Add new paragraph tag
                result.Append("<div style=\"width:100%; text-align:");

                //Append anchor style
                if (par.ParagraphProperties != null && par.ParagraphProperties.Justification != null)
                    switch (par.ParagraphProperties.Justification.Val.Value)
                    {
                        case JustificationValues.Left:
                            result.Append("left;");
                            break;
                        case JustificationValues.Center:
                            result.Append("center;");
                            break;
                        case JustificationValues.Both:
                            result.Append("justify;");
                            break;
                        case JustificationValues.Right:
                        default:
                            result.Append("right;");
                            break;
                    }
                else
                    result.Append("left;");

                //Append text decoration style
                if (par.ParagraphProperties != null && par.ParagraphProperties.ParagraphMarkRunProperties != null && par.ParagraphProperties.ParagraphMarkRunProperties.HasChildren)
                    foreach (OpenXmlElement chield in par.ParagraphProperties.ParagraphMarkRunProperties.ChildElements)
                    {
                        switch (chield.GetType().Name)
                        {
                            case "Bold":
                                result.Append("font-weight:bold;");
                                break;
                            case "Underline":
                                result.Append("text-decoration:underline;");
                                break;
                            case "Italic":
                                result.Append("font-style:italic;");
                                break;
                            case "FontSize":
                                result.Append("font-size:" + ((FontSize)chield).Val.Value + "px;");
                                break;
                            default: break;
                        }
                    }

                result.Append("\">");

                //Add image tag
                IEnumerable<Run> runs = par.Descendants<Run>();
                foreach (Run run in runs)
                {
                    if (run.HasChildren)
                    {
                        foreach (OpenXmlElement chield in run.ChildElements.Where(o => o.GetType().Name == "Picture"))
                        {
                            result.Append(string.Format("<img style=\"{1}\" src=\"data:image/jpeg;base64,{0}\" />", GetBase64Image(imgPart[imgCounter].GetStream()),
                                           ((DocumentFormat.OpenXml.Vml.Shape)chield.ChildElements.Where(o => o.GetType().Name == "Shape").FirstOrDefault()).Style
                                ));
                            imgCounter++;
                        }
                        foreach (OpenXmlElement table in run.ChildElements.Where(o => o.GetType().Name == "Table"))
                        {
                            result.Append("<strong>HERE'S TABLE</strong>");
                        }
                    }
                }

                //Append inner text
                IEnumerable<Text> textElement = par.Descendants<Text>();
                if (par.Descendants<Text>().Count() == 0)
                    result.Append("<br />");

                foreach (Text t in textElement.Where(o=>!tableCellContent.Contains(o.Text.Trim())))
                {
                    result.Append(t.Text);
                }


                result.Append("</div>");
                result.Append(Environment.NewLine);

            }
            else if (section.GetType().Name=="Table")
            {
                result.Append("<table>");
                Table tab = (Table)section;
                foreach (TableRow row in tab.Descendants<TableRow>())
                {
                    result.Append("<tr>");
                    foreach (TableCell cell in row.Descendants<TableCell>())
                    {
                        result.Append("<td>");
                        result.Append(cell.InnerText);
                        tableCellContent.Add(cell.InnerText.Trim());
                        result.Append("</td>");
                    }
                    result.Append("</tr>");
                }
                result.Append("</table>");
            }                
        }


        wordProcessingDoc.Close();

        return result.ToString();
    }

    private static string GetBase64Image(Stream inputData)
    {
        byte[] data = new byte[inputData.Length];
        inputData.Read(data, 0, data.Length);
        return Convert.ToBase64String(data);
    }

推荐答案

尝试以下操作以找到文档中的第一个表.

Try following to find the first table in the document.

Table table = doc.MainDocumentPart.Document.Body.Elements<Table>().First();

这篇关于从DOCX提取表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆