7

我正在尝试在工作表中创建自定义属性,然后检索其值。当我不使用空字符串时,这很好,即"". 当我使用空字符串时,出现此错误:

Run-time error '7':
Out of memory

这是我正在使用的代码:

Sub proptest()

Dim cprop As CustomProperty
Dim sht As Worksheet

Set sht = ThisWorkbook.Sheets("control")
sht.CustomProperties.Add "path", ""

For Each cprop In ThisWorkbook.Sheets("control").CustomProperties
    If cprop.Name = "path" Then
        Debug.Print cprop.Value
    End If
Next

End Sub

代码在Debug.Print cprop.value. 我不应该能够将属性设置为""最初吗?

4

4 回答 4

2

使用vbNullChar它可以工作,示例:

Sub proptest()
  Dim sht As Worksheet
  Set sht = ThisWorkbook.Sheets("control")

  ' On Error Resume Next
  sht.CustomProperties.Item(1).Delete
  ' On Error GoTo 0

  Dim pathValue As Variant
  pathValue = vbNullChar

  Dim pathCustomProperty As CustomProperty
  Set pathCustomProperty = sht.CustomProperties.Add("path", pathValue)

  Dim cprop As CustomProperty
  For Each cprop In ThisWorkbook.Sheets("control").CustomProperties
      If cprop.Name = "path" Then
          Debug.Print cprop.Value
      End If
  Next

End Sub
于 2012-11-06T07:16:10.763 回答
1

我认为从 Daniel Dusek 的评论和回答中可以清楚地看出这是无法做到的。该属性应至少包含 1 个字符才能有效,不允许使用空字符串,并且在调用 .Value 时会出错。

所以你Add这个属性的长度为 1 或更多,当没有实际值被分配给它时string,你再次使用这个属性。Delete

于 2012-11-06T12:32:14.283 回答
0

如前所述,无法设置空字符串。

一个简单的解决方法是使用一个神奇的词或字符,例如~Empty(或任何对你来说足够证明的东西):

Dim MyProperty As Excel.CustomProperty = ...
Dim PropertyValue As String = If(MyProperty.Value = "~Empty", String.Empty, MyPropertyValue)

一个稍微昂贵但 100% 安全的解决方法是使用一个字符开始自定义属性的所有值,然后您总是将其剥离。访问值时,系统地删除第一个字符:

Dim MyProperty As Excel.CustomProperty = ...
Dim PropertyValue As String = Strings.Mid(MyProperty.Value, 2)

你可以编写一个扩展来让你的生活更轻松:

<System.Runtime.CompilerServices.Extension>
Function ValueTrim(MyProperty as Excel.CustomProperty) As String
    Return Strings.Mid(MyProperty.Value, 2)
End Function

现在你可以像这样使用它:Dim MyValue As String = MyProperty.ValueTrim

添加自定义属性时使用相反的原则:

<System.Runtime.CompilerServices.Extension>
Function AddTrim(MyProperties As Excel.CustomProperties, Name As String, Value As String) as Excel.CustomProperty
    Dim ModifiedValue As String = String.Concat("~", Value) 'Use ~ or whatever character you lie / Note Strig.Concat is the least expensive way to join two strings together.
    Dim NewProperty As Excel.CustomProperty = MyProperties.Add(Name, ModifiedValue)      
    Return NewProperty 
End Function

像这样使用:MyProperties.AddTrim(Name, Value)

希望这可以帮助遇到这个问题的其他人..

于 2020-01-10T14:16:10.633 回答
0

基于其他答案和一些试验和错误,我编写了一个类来包装一个Worksheet.CustomProperty.

工作表属性:类

设置并获取 a 的值Worksheet.CustomProperty并测试 aWorksheet是否具有CustomProperty

VERSION 1.0 CLASS
Attribute VB_Name = "WorksheetProperty"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'@Folder("Classes")
'@PredeclaredId

Option Explicit
Private Type TMembers
    Name As String
    Worksheet As Worksheet
End Type
Private this As TMembers

Public Property Get Create(pWorksheet As Worksheet, pName As String) As WorksheetProperty
    With New WorksheetProperty
        Set .Worksheet = pWorksheet
        .Name = pName
        Set Create = .Self
    End With
End Property

Public Property Get Self() As WorksheetProperty
    Set Self = Me
End Property

Public Property Get Worksheet() As Worksheet
    Set Worksheet = this.Worksheet
End Property

Public Property Set Worksheet(ByVal pValue As Worksheet)
    Set this.Worksheet = pValue
End Property

Public Property Get Name() As String
    Name = this.Name
End Property

Public Property Let Name(ByVal pValue As String)
    this.Name = pValue
End Property

Public Property Get Value() As String
    Dim P As CustomProperty
    For Each P In Worksheet.CustomProperties
        If P.Name = Name Then
            Value = P.Value
            Exit Property
        End If
    Next
End Property

Public Property Let Value(ByVal pValue As String)
    Delete
    Worksheet.CustomProperties.Add Name:=Name, Value:=pValue
End Property

Public Property Get hasCustomProperty(pWorksheet As Worksheet, pName As String) As Boolean
    Dim P As CustomProperty
    For Each P In pWorksheet.CustomProperties
        If P.Name = pName Then
            hasCustomProperty = True
            Exit Property
        End If
    Next
End Property


Public Sub Delete()
     Dim P As CustomProperty
    For Each P In Worksheet.CustomProperties
        If P.Name = Name Then
            P.Delete
            Exit For
        End If
    Next
End Sub

用法

我的自定义 Unit 类有几个属性返回一个 WorksheetProperty。它使我的数据库与我的工作表同步变得非常容易。

Public Function hasMeta(Ws As Worksheet) As Boolean
    hasMeta = WorksheetProperty.hasCustomProperty(Ws, MetaName)
End Function

Public Property Get Id() As WorksheetProperty
    Set Id = WorksheetProperty.Create(this.Worksheet, "id")
End Property

Public Property Get CourseID() As WorksheetProperty
    Set CourseID = WorksheetProperty.Create(this.Worksheet, "course_id")
End Property

Public Property Get Name() As WorksheetProperty
    Set Name = WorksheetProperty.Create(this.Worksheet, "unit_name")
End Property

简单用法

'ActiveSheet has a CustomProperty
Debug.Print WorksheetProperty.hasCustomProperty(ActiveSheet, "LastDateSynced")

'Set a CustomProperty
WorksheetProperty.Create(ActiveSheet, "LastDateSynced").Value = Now

'Retrieve a CustomProperty
Debug.Print WorksheetProperty.Create(ActiveSheet, "LastDateSynced").Value
于 2021-02-03T15:41:52.447 回答