使用OpenXML在Word中获取复选框

9

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

你可能认为Paragraph.ControlPropertiesPart或Paragraph.Descendents()可以实现这一点,但在每一个情况下我都返回了null类型。

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

欢迎提供建议。


你是否正在使用复选框内容控件? - CoderDennis
1个回答

12
以下代码展示了如何通过在文档正文上使用Decendants<CheckBox>()方法来枚举Word文档中的所有复选框。
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属性为nullBEGIN EDIT 我想扩展我的答案。实际上,在MS Word开发人员选项卡上有两种复选框控件-传统复选框和ActiveX控件复选框。上面显示的代码可用于枚举文档中的传统复选框(请参见这个article以了解如何创建传统复选框)。
据我所知,您无法使用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();

编辑结束

编辑2

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

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

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");  
     }           
   }
}

编辑结束2

希望这有所帮助。


这就是我期望的工作方式,但是我在代码中放置的三个复选框仍然没有被捕获。我无法想象我做错了什么。除非有不同类型的复选框。我创建了一个示例文档,并从开发人员选项卡中的控件组中插入了复选框。 - Phil.Wheeler
@Phil.Wheeler:你使用ActiveX复选框还是旧版复选框控件?请注意,上述代码仅适用于旧版复选框。 - Hans
@Phil.Wheeler:我已更新我的答案。实际上,有两种复选框 - 传统复选框和ActiveX控件复选框。请参见我上面的答案,了解如何枚举ActiveX复选框。 - Hans
Word 2010增加了一种全新的复选框类型——复选框内容控件。我认为内容控件不是ActiveX,而且绝对不是遗留的。 - CoderDennis
@Phil.Wheeler:我已更新我的答案,展示如何枚举Word2010中的新复选框控件。因此,有三种类型的复选框:传统、ActiveX和内容复选框。 - Hans
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接