使用 OpenXML 在 Word 中获取复选框

发布于 2024-12-18 19:24:47 字数 209 浏览 2 评论 0原文

如何使用 OpenXML 获取嵌入到 Word 文档中的 CheckBox 控件的句柄?

您可能会认为 Paragraph.ControlPropertiesPart 或 Paragraph.Descendents() 会实现某些目标,但在每种情况下我都会返回 null 类型。

我可以使用实际的 XML 结构遍历文档树,但这看起来很麻烦。

欢迎提出建议。

How does one get a handle to a CheckBox control that's embedded in a Word document using OpenXML?

You would think that either Paragraph.ControlPropertiesPart or Paragraph.Descendents() would achieve something but in every single case I get a null type returned.

I can traverse down the document tree using the actual XML structure, but this seems cumbersome.

Suggestions welcome.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沙沙粒小 2024-12-25 19:24:47

下面的代码显示了如何枚举Word文档中的所有复选框
在文档主体上使用 Decendants() 方法。

using (WordprocessingDocument doc = WordprocessingDocument.Open("c:\\temp\\checkbox.docx", true))
{
  foreach (CheckBox cb in doc.MainDocumentPart.Document.Body.Descendants<CheckBox>())
  {
    Console.Out.WriteLine(cb.LocalName);

    FormFieldName cbName = cb.Parent.ChildElements.First<FormFieldName>();
    Console.Out.WriteLine(cbName.Val);

    DefaultCheckBoxFormFieldState defaultState = cb.GetFirstChild<DefaultCheckBoxFormFieldState>();
    Checked state = cb.GetFirstChild<Checked>();

    Console.Out.WriteLine(defaultState.Val.ToString());

    if (state.Val == null) // In case checkbox is checked the val attribute is null
    {
      Console.Out.WriteLine("CHECKED");
    }
    else
    {
      Console.Out.WriteLine(state.Val.ToString());
    }
  }
}

要确定给定复选框输入元素的名称,您必须访问
CheckBox 实例的 Parent 属性,然后搜索 FormFieldName 元素(要为复选框指定名称,请使用 Microsoft Word 中的“属性”对话框) 。

DefaultCheckBoxFormFieldState Val 属性保存复选框的默认状态。
此外,Checked 元素的 Val 属性保存实际的选中状态
CheckBox 实例的。请注意,对于 Microsoft Word 2007,如果满足以下条件,则 Val 属性为 null
复选框被选中。

开始编辑

我想扩展我的答案。事实上,MS Word 开发人员选项卡上有两种复选框控件 - 传统复选框和 ActiveX 控件复选框。上面显示的代码可用于枚举 Word 文档中的旧复选框(请参阅此 有关如何创建旧复选框的文章)。

据我所知,您无法使用 OpenXML SDK 获取/设置 ActiveX 复选框的值。
不过,您可以使用以下代码枚举 ActiveX 控件:

foreach (Control ctrl in doc.MainDocumentPart.Document.Body.Descendants<Control>())
{
   Console.Out.WriteLine(ctrl.Id);
   Console.Out.WriteLine(ctrl.Name);
   Console.Out.WriteLine(ctrl.ShapeId);
}

要确定给定的 Control 是否为复选框,您必须检查 Control 的类 ID。复选框的类 ID 为 {8BD21D40-EC42-11CE-9E0D-00AA006002F3}
这是一个获取类ID的代码示例(我不知道是否有更简单的方法...):

OpenXmlPart part = doc.MainDocumentPart.GetPartById(ctrl.Id);
OpenXmlReader re = OpenXmlReader.Create(part.GetStream());
re.Read();
OpenXmlElement el = re.LoadCurrentElement();          
if(el.GetAttribute("classid", el.NamespaceUri).Value == "{8BD21D40-EC42-11CE-9E0D-00AA006002F3}")
{
  Console.WriteLine("Checkbox found...");
}
re.Close();

END EDIT

EDIT 2

我没有意识到Word 2010 中有一个新的复选框控件(感谢 Dennis
帕尔默)。

要枚举这些新的复选框控件,您可以使用以下代码:

using (WordprocessingDocument doc = WordprocessingDocument.Open(filename, true))
{
   MainDocumentPart mp = doc.MainDocumentPart;

   foreach(SdtContentCheckBox cb in mp.Document.Body.Descendants<SdtContentCheckBox>())
   {         
     if(cb.Checked.Val == "1");
     {
       Console.Out.WriteLine("CHECKED");  
     }           
   }
}

END EDIT 2

希望这会有所帮助。

The code below shows how to enumerate all checkboxes in a word document by
using the Decendants<CheckBox>() method on the docuement's body.

using (WordprocessingDocument doc = WordprocessingDocument.Open("c:\\temp\\checkbox.docx", true))
{
  foreach (CheckBox cb in doc.MainDocumentPart.Document.Body.Descendants<CheckBox>())
  {
    Console.Out.WriteLine(cb.LocalName);

    FormFieldName cbName = cb.Parent.ChildElements.First<FormFieldName>();
    Console.Out.WriteLine(cbName.Val);

    DefaultCheckBoxFormFieldState defaultState = cb.GetFirstChild<DefaultCheckBoxFormFieldState>();
    Checked state = cb.GetFirstChild<Checked>();

    Console.Out.WriteLine(defaultState.Val.ToString());

    if (state.Val == null) // In case checkbox is checked the val attribute is null
    {
      Console.Out.WriteLine("CHECKED");
    }
    else
    {
      Console.Out.WriteLine(state.Val.ToString());
    }
  }
}

To determine the name of a given checkbox input element you have to access the
Parent property of the CheckBox instance and then search for the FormFieldName element (to assign a name to a checkbox use the Properties Dialog in Microsoft Word).

The DefaultCheckBoxFormFieldState Val property holds the default state for the checkbox.
Furthermore the Val property of the Checked element holds the actual checked state
of the CheckBox instance. Note, for Microsoft Word 2007 the Val property is null if
the checkbox is checked.

BEGIN EDIT

I'd like to extend my answer. In fact, there are two kinds of checkbox controls on the MS Word developer tab - a legacy checkbox and an ActiveX control checkbox. The code shown above can be used to enumerte legacy checkboxes in a word document (see this article on how to create a legacy checkbox).

As far as I know, you can't use the OpenXML SDK to get/set values for an ActiveX checkbox.
However you can enumerate ActiveX controls using the following code:

foreach (Control ctrl in doc.MainDocumentPart.Document.Body.Descendants<Control>())
{
   Console.Out.WriteLine(ctrl.Id);
   Console.Out.WriteLine(ctrl.Name);
   Console.Out.WriteLine(ctrl.ShapeId);
}

To determine whether or not a given Control is a checkbox you have to ckeck the class ID of the Control. The class ID of a checkbox is {8BD21D40-EC42-11CE-9E0D-00AA006002F3}.
Here is a code sample to get the class ID (I don't know if there is an easier way...):

OpenXmlPart part = doc.MainDocumentPart.GetPartById(ctrl.Id);
OpenXmlReader re = OpenXmlReader.Create(part.GetStream());
re.Read();
OpenXmlElement el = re.LoadCurrentElement();          
if(el.GetAttribute("classid", el.NamespaceUri).Value == "{8BD21D40-EC42-11CE-9E0D-00AA006002F3}")
{
  Console.WriteLine("Checkbox found...");
}
re.Close();

END EDIT

EDIT 2

I didn't realize that there is a new checkbox control in Word 2010 (Thanks to Dennis
Palmer).

To enumerate those new checkbox controls you can use the following code:

using (WordprocessingDocument doc = WordprocessingDocument.Open(filename, true))
{
   MainDocumentPart mp = doc.MainDocumentPart;

   foreach(SdtContentCheckBox cb in mp.Document.Body.Descendants<SdtContentCheckBox>())
   {         
     if(cb.Checked.Val == "1");
     {
       Console.Out.WriteLine("CHECKED");  
     }           
   }
}

END EDIT 2

Hope, this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文