【问题标题】:How to read Visio Shape's text properly如何正确阅读 Visio Shape 的文本
【发布时间】:2018-04-03 13:44:22
【问题描述】:

我正在尝试将 VBA 代码传输到 C#,以便我制作的表单应用程序是独立的。我在尝试从形状内(在一个组中)的形状中获取文本时遇到问题。这是一个完美运行的 VBA 示例。

Dim text as String
text = groupShape.shapes.item("rectangle").text

这是返回正确的值。 在 C# 中,我使用的是 microsoft.office.interop.visio.dll 参考。我已经能够很好地读取形状名称,所以我知道我的应用程序和文档对象工作正常。在 C# 中,上面的代码如下所示:

var text = "";
text = Doc.Shapes.ItemU("groupShape").Shapes.ItemU("rectangle").text

这没有返回正确的值。它是说它会返回“Object”,所以我相信它不是返回一个字符串而是一个对象。

为了返回文本,我可以做些什么来解决这个问题?谢谢!

编辑: 这是我正在编写的实际代码。 vba 和 c#

VBA:

Dim tempShape As Shape

Set tempShape = ActiveDocument.Pages(pageName).Shapes.Item("MainTable")

txtJobName.value = tempShape.Shapes.Item("textJobName").Text

c#

IVisio.Shape tempShape = Doc.Pages[Loaded_Page.Name].Shapes.ItemU["MainTable"];

 Txt_JobName.Text = tempShape.Shapes.ItemU["textJobName"].Characters.Text;

另一个编辑: 我还尝试通过引用文本所在的单元格来进入形状数据属性,但仍然没有运气。

Txt_JobName.Text = tempShape.Shapes.ItemU["textJobName"].CellsSRC[8, 0, 0].ResultStr[0];

【问题讨论】:

    标签: c# vba com-interop visio


    【解决方案1】:

    首先,尝试使用 .Item 而不是 .ItemU,这两个是不同的功能。默认值(您在 VBA 中隐式使用的)是Item。您实际上可能在 c# 中处理不同的形状

    其次,.Text 应该以大写 T 开头,小 t 的代码不应该编译。确保小写的.text 不是您从某处导入的扩展方法,(与 Visio 无关)

    第三个警告 - 为了确保从形状中获取文本,如您在 UI 中看到的那样,最好使用 shape.Characters.Text,因为如果形状包含字段,shape.Text 将返回占位符('obj')字段文本应该去的那些地方。但这适用于 VBA 和 C#

    第四个.. VBA 中的groupShape 似乎是一个变量名,而不是形状名。从代码中不清楚该组形状的名称是什么。你如何在VBA中得到那个?可能值得检查。

    【讨论】:

    • 我用实际代码更新了我的问题。我已经完成了所有这些检查:/ 在 c# 中,库中不存在 .item,只有 .itemu
    • @jediderek 如果互操作库中有 get_Item 方法,请使用它。
    • @Mat'sMug .ItemU 是 get_item 方法。
    • 是的,而且由于 COM 互操作本身就是不稳定的,您应该更喜欢使用 getter 方法而不是索引器和属性。
    • @Mat'sMug 你会推荐一个更好的库吗?
    【解决方案2】:

    我对 Visio 类型库不是很熟悉,但是这个:

    groupShape.shapes.item("rectangle")
    

    正在返回一个Shape 对象。抓住那个对象引用,而不是用另一个点丢弃它。 VBA 在这里“很有帮助”,并且很高兴地让您编写只能在运行时解决的后期绑定调用 - C# 只会允许使用 dynamic 关键字,并且您通常不想针对 @987654324 进行编码@ - 你想使用强类型:

    Dim rectangle As Shape
    Set rectangle = groupShape.shapes.item("rectangle")
    
    Dim rectangleText As String
    rectangleText = rectangle.Text
    

    C#/互操作代码也需要这样做:

    var groupShape = (Shape)Doc.Shapes.ItemU("groupShape");
    var rectangle = (Shape)groupShape.Shapes.ItemU("rectangle");
    var rectangleText = rectangle.Text // assuming Text is defined on the Shape interface
    

    换句话说,始终注意您正在使用的类型;如果成员返回 object 并且您需要它是更具体的类型,则需要进行适当的转换,然后才能对成员调用进行编译时验证,或者转换为 dynamic 如果您不在乎用于编译时验证并将它们推迟到运行时:

    var text = (string)((dynamic)groupShape.Shapes.ItemU("rectangle")).Text
    

    请注意string 的演员; text 将是 string。忘记那个演员表,你的代码将不得不处理dynamic 像癌症一样在整个执行路径中传播并破坏你的类型安全——你不希望这样。

    【讨论】:

    • 你说的有道理,但遗憾的是没有对我有利。我尝试像在您的示例中一样创建第二个形状对象,并尝试抓取文本,但结果仍然相同(我还尝试了其他一些方法,使用您提供的信息以及转换为动态/字符串)。
    • 我不知道它是什么,但突然之间这工作了。以前不行,现在可以了。
    • 可能是括号放错了。
    【解决方案3】:

    与往常一样,我来找出 .Text 返回“Obj”的原因是该形状中没有任何文本。如果有文本,它将返回它。我太沉迷于回归,“Obj”。我想知道如果形状中没有文本,为什么它不返回空文本或 null。无论如何,关于这个问题的所有其他答案都非常有帮助,它们让我找到了我的问题。

    【讨论】:

    • 这意味着,你的形状有字段。这是我的第 3 项“字段”。使用 shape.Characters.Text 检查 Visio 文档以了解哪些字段。
    猜你喜欢
    • 2022-08-24
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多