OpenXML SDK getting ActiveX controls value

我与影子孤独终老i 提交于 2020-01-05 07:14:38

问题


For one of my projects in college I had to create a test as a Word document and add some ActiveX forms in it to be completed by another person. After this I had to programmatically extract the answers from it and put a grade on the test.

I used OpenXML SDK for processing the document, but it gave me headaches because I couldn't find a way to get the ActiveX values.

So what was the solution?


回答1:


After searching the Internet and a bit of sniffing on the document I have found that the ActiveX control data can be found in a document part specified by the control ID. Determining the type of control is a bit tricky because I didn't find any documentation about this. Apparently you must get the "classid" attribute from a control and try to match it to the classids you know. Below is the code for determining the values for three types of controls. The rest of the ids are marked as not known and you can match them intuitively to the ones you added in the document.


using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Xml;
using System.IO;
using System.Text;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Packaging;

namespace OpenXMLTest
{
    class Program
    {
        const string textBoxId = "{8BD21D10-EC42-11CE-9E0D-00AA006002F3}";
        const string radioButtonId = "{8BD21D50-EC42-11CE-9E0D-00AA006002F3}";
        const string checkBoxId = "{8BD21D40-EC42-11CE-9E0D-00AA006002F3}";

        static void Main(string[] args)
        {
            string fileName = @"C:\Users\Andy\Desktop\test_l1demo.docx";
            using (WordprocessingDocument doc = WordprocessingDocument.Open(fileName, false))
            {
                foreach (Control control in doc.MainDocumentPart.Document.Body.Descendants())
                {
                    Console.WriteLine();
                    Console.WriteLine("Control {0}:", control.Name);
                    Console.WriteLine("Id: {0}", control.Id);

                    displayControlDetails(doc, control.Id);
                }
            }

            Console.Read();
        }

        private static void displayControlDetails(WordprocessingDocument doc, StringValue controlId)
        {
            string classId, type, value;

            OpenXmlPart part = doc.MainDocumentPart.GetPartById(controlId);
            OpenXmlReader reader = OpenXmlReader.Create(part.GetStream());
            reader.Read();
            OpenXmlElement controlDetails = reader.LoadCurrentElement();

            classId = controlDetails.GetAttribute("classid", controlDetails.NamespaceUri).Value;

            switch (classId)
            {
                case textBoxId:
                    type = "TextBox";
                    break;
                case radioButtonId:
                    type = "Radio Button";
                    break;
                case checkBoxId:
                    type = "CheckBox";
                    break;
                default:
                    type = "Not known";
                    break;
            }

            value = "No value attribute"; //displays this if there is no "value" attribute found
            foreach (OpenXmlElement child in controlDetails.Elements())
            {
                if (child.GetAttribute("name", controlDetails.NamespaceUri).Value == "Value")
                {
                    //we've found the value typed by the user in this control
                    value = child.GetAttribute("value", controlDetails.NamespaceUri).Value;
                }
            }

            reader.Close();

            Console.WriteLine("Class id: {0}", classId);
            Console.WriteLine("Control type: {0}", type);
            Console.WriteLine("Control value: {0}", value);

        }
    }
}


来源:https://stackoverflow.com/questions/13377752/openxml-sdk-getting-activex-controls-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!