铸造 编码规则
介绍 (Introduction)
本文是关于数据转换的。 我将介绍VBA / VB6显式转换。 它与飞蝇钓鱼,卷筒钓鱼,冲浪钓鱼,表演或断肢没有任何关系。 您可能已经进行了一些转换,却不知道,因为VB隐式为您执行了一些转换。 尽管这是一个教程,但我包含了一些提示和技巧。
Firstly, I'd like to acknowledge the genesis of this article. The primary impetus to start writing was reading Jim Dettman's excellent article (http:/A_12.html) on the MS-Access DLookup function. Secondly, I had recently completed an upgrade to one of my Access applications using and enhancing the DLookup function with some data type casting. Thirdly, from my involvement with the local Delphi user group and answering questions in the Delphi TA, I've become a fan of Delphi's QuotedStr() function. In general, I look back on so many EE questions in various Topic Areas that involved data type casting, that I thought it worth writing an article.
首先,我想承认本文的起源。 开始撰写文章的主要动力是阅读Jim Dettman关于MS-Access DLookup函数的出色文章( http:/A_12.html )。 其次,我最近使用某些数据类型转换并使用DLookup功能增强了对我的Access应用程序的升级。 第三,由于我参与了当地的Delphi用户组并在Delphi TA中回答了问题,因此我成为了Delphi QuotedStr()函数的支持者。 总的来说,我回顾了涉及数据类型转换的各个主题领域中的许多EE问题,我认为值得写一篇文章。
文章主题 (Article Topics)
What is Casting?
什么是铸造?
Common places to encounter casting
常见的铸件场所
Why would this ever be a problem?
为什么这会成为问题?
Problems with casting
铸造问题
Intrinsic Casting functions in VBA/VB6
VBA / VB6中的固有转换功能
Casting Tricks & Tips
铸造技巧
什么是铸造? (What is Casting?)
强制转换会导致变量的内容或表达式/文字被视为不同类型的数据。 数据转换发生在临时存储位置。 有几种方法可以在VB中转换数据。 由于大多数人应该熟悉串联,因此您应该了解串联是字符串(数据类型)表达式之间的操作。 将数字或日期连接到字符串时,会有一些隐式转换。 虽然有一些函数可以在更改数据类型的同时提取其一部分数据
(e.g. Format(Date(),"dddd")), this article is about a data type change of the entire data.
(例如Format(Date(),“ dddd”)),本文是关于整个数据的数据类型更改。
常见的铸件场所 (Common places to encounter casting)
Dynamic SQL- building a SQL statement through concatenation with local variables, control values and other database data.
动态SQL-通过与局部变量,控制值和其他数据库数据的连接来构建SQL语句。
VBA code- converting a string to a byte array as the first part of an encryption routine.
VBA代码-将字符串转换为字节数组作为加密例程的第一部分。
Dim bText() As Byte
昏暗bText()作为字节
bText = StrConv(parmPlainText, vbFromUnicode)
bText = StrConv(parmPlainText,vbFromUnicode)
Function and Subroutine calls- defining a parameter as a particular data type may require the calling/invoking code to cast an express to a matching data type. Also, a routine may have to cast data passed in through a Variant parameter.
函数和子例程调用-将参数定义为特定的数据类型可能需要调用/调用代码将Express转换为匹配的数据类型。 同样,例程可能必须强制转换通过Variant参数传入的数据。
T-SQL- If you have seen many T-SQL scripts, you have probably noticed the use of the CAST() and CONVERT() functions.
T-SQL-如果您看过许多T-SQL脚本,则可能已经注意到CAST()和CONVERT()函数的使用。
Excel- has several workbook functions to cast one type of data into another, such as DEC2HEX(), DEC2BIN(), HEX2DEC(), COMPLEX().
Excel-具有多个工作簿功能,可以将一种数据类型转换为另一种数据类型,例如DEC2HEX(),DEC2BIN(),HEX2DEC(),COMPLEX()。
为什么这会成为问题? (Why would this ever be a problem?)
有时候您会为了方便而牺牲便利性和灵活性。 如果您的程序读取CSV文件,则可能需要将这些值读取到String或Variant数据类型的局部变量中,然后将某些数据转换为特定的数据类型以供以后处理。
铸造问题 (Problems with casting)
Sometimes you get an error message that doesn't quite describe casting as the solution
有时您会收到一条错误消息,并没有将铸造描述为解决方案
Error 13: Type Mismatch
错误13:类型不匹配
Error 49: Bad DLL calling convention
错误49:错误的DLL调用约定
Error 1006: Unable to get the [property name] property of the [object] class
错误1006:无法获取[object]类的[property name]属性
VB var types are different than DB var types
VB var类型与DB var类型不同
x=#1/2/2009#:?x,vartype(x),vbvartype.vbDate,TypeName(x),dbDate
1/2/2009 7 7 Date 8
x=1/2:?x,vartype(x),vbvartype.vbDouble,TypeName(x),dbDouble
0.5 5 5 Double 7
x=2009:?x,vartype(x),vbvartype.vbInteger,TypeName(x),dbInteger
2009 2 2 Integer 3
x=200900:?x,vartype(x),vbvartype.vbLong,TypeName(x),dbLong
200900 3 3 Long 4
x="aikimark":?x,vartype(x),vbvartype.vbString,TypeName(x),dbText
aikimark 8 8 String 10
x=true:?x,vartype(x),vbvartype.vbBoolean,TypeName(x),dbBoolean
True 11 11 Boolean 1
Sometimes the intrinsic casting functions don't work the way you expect (or want)
有时,固有的强制转换功能无法按您期望的方式工作
date conversions 日期转换?cdate("1/2/2009")
1/2/2009
?cdate(1/2/2009)
12:00:22 AM
Number concatenation -- which is why I always use the & concatenation operator
数字串联-这就是为什么我总是使用&串联运算符
a=1
b=2
?a + b
3
?cstr(a) + cstr(b)
12
VBA / VB6中的固有转换功能 (Intrinsic Casting functions in VBA/VB6)
CBool()
CByte()
CCur()
CDate()
CDbl()
CDec()
CInt()
CLng()
CSng()
CStr()
CVar()
Note: the .Net framework is full of casting features, such as the .ToString method. I will not cover these in this article.
注意:.Net框架具有强制转换功能,例如.ToString方法。 我将不在本文中介绍这些内容。
铸造技巧 (Casting Tricks & Tips)
Dynamic SQL 动态SQLJDettman's article introduced you to delimited string variables in a DLookup() criteria parameter. In addition, there are date variables, requiring a pound sign (#) delimiter. Here is a general purpose function that you can use to properly delimit your variables, no matter what their data type. Sometimes we cast data by the delimiters around expressions we type into our code. As Jim highlighted, the data type of the field needs to match the data type of the compared value/expression. When they don't match we frequenly receive a "Data type mismatch in criteria expression" error (-2147217913), but sometimes, we just don't get the results we expected.
JDettman的文章向您介绍了DLookup()标准参数中的定界字符串变量。 此外,还有日期变量,需要井号(#)分隔符。 这是一个通用函数,无论它们的数据类型如何,都可以使用它来正确地定界变量。 有时,我们使用定界符将数据键入到代码中,然后使用定界符强制转换数据。 正如Jim所强调的,字段的数据类型需要与比较值/表达式的数据类型匹配。 当它们不匹配时,我们通常会收到“条件表达式中的数据类型不匹配”错误(-2147217913),但是有时,我们只是无法获得预期的结果。
Public Function Delimed(parmVar) As String
Const QuoteChar = """"
Const PoundChar = "#"
If VarType(parmVar) = vbDate Or IsDate(parmVar) Then
Delimed = PoundChar & parmVar & PoundChar
ElseIf IsNumeric(parmVar) Then
Delimed = CStr(parmVar)
ElseIf VarType(parmVar) = vbString Then
Delimed = QuoteChar & parmVar & QuoteChar
Else
Delimed = CStr(parmVar)
End If
End Function
Usage: 用法: This example revisits the DLookup article's example set, comparing column values in a table.
本示例重新访问DLookup文章的示例集,比较表中的列值。
Dim vCompany As Variant
Dim sCompany As String
Dim lCompany As Long
Dim vFrom As Variant
Dim vTo As Variant
Dim sSQL As String
Dim rs As Recordset
vCompany = 2525
sCompany = "2525"
lCompany = 2525
sSQL = "Select * From CompanyTable Where ID =" & Delimed(vCompany)
Debug.Print "vCompany=ID", sSQL
sSQL = "Select * From CompanyTable Where ID =" & Delimed(sCompany)
Debug.Print "sCompany=ID", sSQL
sSQL = "Select * From CompanyTable Where ID =" & Delimed(lCompany)
Debug.Print "lCompany=ID", sSQL
vCompany = "EE Publishing"
sCompany = "EE Publishing"
sSQL = "Select * From CompanyTable Where CompanyName =" & Delimed(vCompany)
Debug.Print "vCompany=CompanyName", sSQL
sSQL = "Select * From CompanyTable Where CompanyName =" & Delimed(sCompany)
Debug.Print "sCompany=CompanyName", sSQL
vFrom = "2001-10-1"
vTo = "10/11/2009"
sSQL = "Select * From CompanyTable Where JoinDate Between " & Delimed(vFrom) & " And " & Delimed(vTo)
Debug.Print "vFrom/vTo", sSQL
Result of the Delimed() function on the SQL string
SQL字符串上的Delimed()函数的结果
=== Immediate Window ============
vCompany=ID Select * From CompanyTable Where ID =2525
sCompany=ID Select * From CompanyTable Where ID =2525
lCompany=ID Select * From CompanyTable Where ID =2525
vCompany=CompanyName Select * From CompanyTable Where CompanyName ="EE Publishing"
sCompany=CompanyName Select * From CompanyTable Where CompanyName ="EE Publishing"
vFrom/vTo Select * From CompanyTable Where JoinDate Between #2001-10-1# And #10/11/2009#
=================================
Warning: The Delimed() function is not perfect. It can not overcome limitations in the runtime environment. This is most evident with the following date example executed in the Immediate window. If you ever created dynamic SQL with a date string that was not #-delimited, then this should help you understand what value was being passed to the database query parser.
警告:Delimed()函数并不完美。 它无法克服运行时环境中的限制。 在立即窗口中执行以下日期示例时,这一点最为明显。 如果您使用日期编号不是#分隔符创建动态SQL,那么这应该可以帮助您了解将什么值传递给数据库查询解析器。
=== Immediate Window ============
?Delimed("12/1/2001")
#12/1/2001#
?Delimed(12/1/2001)
5.99700149925037E-03
=================================
Casting for my own convenience 为自己方便铸造 In a recent application, I created a configuration settings table to help with the migration of the database from development (me), to the on-site test environment, to the production environment. Originally, there were two text columns, containing the config-name and config-value. I used the DLookup() function to retrieve values from the table. I ran into some quirks of the DLookup() function that cause me to add a third text column to the table (config-datatype) and wrap the DLoopkup results in a function that cast the results into the desired data type. This made the application code much simpler. When the database is opened, application code can match the attached table connection string against that in the configuration settings table and reattach them, if necessary. There are certain actions that don't work in my development environment, so I look at the DevEnvironment config-value to detect this. When the tester gets a new copy of the application, he renames the configuration settings tables and restarts the database. He repeats this process when moving his tested database into production.
在最近的应用程序中,我创建了一个配置设置表,以帮助数据库从开发(me)迁移到现场测试环境,再到生产环境。 最初,有两个文本列,分别包含config-name和config-value。 我使用DLookup()函数从表中检索值。 我遇到了DLookup()函数的一些怪癖,这些怪癖使我向表中添加了第三文本列(config-datatype),并将DLoopkup结果包装到一个将结果转换为所需数据类型的函数中。 这使应用程序代码更加简单。 打开数据库后,应用程序代码可以将附加的表连接字符串与配置设置表中的字符串进行匹配,并在必要时重新附加它们。 有些操作在我的开发环境中不起作用,因此我查看了DevEnvironment的配置值来检测到这一点。 当测试人员获得应用程序的新副本时,他将重命名配置设置表并重新启动数据库。 当他将测试的数据库投入生产时,他重复了这一过程。
My DLookup() problems were:
我的DLookup()问题是:
The returned Variant data type isn't typed
未键入返回的Variant数据类型
If a value isn't found, the function returns Null
如果找不到值,则该函数返回Null
Null values may be fine for assigning to fields, but they can't be assigned to string variables and some controls
空值可能适合分配给字段,但是不能将它们分配给字符串变量和某些控件
Public Function GetConfigSetting(parmConfigName As String) As Variant
Dim varValue As Variant
Dim strType As String
varValue = DLookup("ConfigValue", "ConfigurationSettings", "ConfigName = " & Delimed(parmConfigName))
If IsNull(varValue) Then
GetConfigSetting = vbNullString
Else
strType = DLookup("ConfigDataType", "ConfigurationSettings", "ConfigName = " & Delimed(parmConfigName))
Select Case strType
Case "Text"
GetConfigSetting = CStr(varValue)
Case "Long"
GetConfigSetting = CLng(varValue)
Case "Single"
GetConfigSetting = CSng(varValue)
Case "Double"
GetConfigSetting = CDbl(varValue)
Case "Date"
GetConfigSetting = CDate(varValue)
Case "Boolean"
GetConfigSetting = CBool(varValue)
Case Else
GetConfigSetting = varValue
End Select
End If
End Function
ConfigurationSettings table ConfigurationSettings表 ID ConfigName ConfigValue ConfigDataType
1 ImportPath C:\Temp\ Text
2 DevEnvironment True Boolean
3 BE_Connect C:\Specimen DB 9-3\Spec Database_BE.mdb Text
4 ActivityLog_Connect C:\Specimen DB 9-3\Activity Log.mdb Text
5 Snapshot_Connect C:\ Specimen DB 9-3\Spec Snapshot.mdb Text
6 BE_Pattern *_BE.mdb Text
7 ActivityLog_Pattern *Activity Log.mdb Text
8 Snapshot_Pattern *SpecDBMS Snapshot.mdb Text
Fieldname DataType FieldLength
ID AutoNumber 4
ConfigName Text 50
ConfigValue Text 255
ConfigDataType Text 50
ConfigDataType Lookup tab is defined as:
ConfigDataType查找选项卡定义为:
RowSource is a one column value list: Text;Long;Single;Double;Date;Boolean
RowSource是一列值列表:Text; Long; Single; Double; Da te; Boolean
BoundColumn: 1
绑定列:1
ColumnWidths: 2"
列宽:2英寸
========================================= ========================= ========== =========== BONUS MATERIAL ==================
======奖励材料==================
=========================================
========================= ========== =====
性能提示: (Performance Tip:)
大约十年前,我向本地VB用户组进行了性能演示。 我的测试之一是Select Case语句,与在GetConfigSetting()函数中看到的非常相似。 如果创建将非常频繁执行的配置设置表,则最好更改ConfigDataType字段查找选项卡。 整数值的比较比字符串值的比较要快得多。
Also, note that the ordering of compared values will also help performance, placing the most likely encountered values nearer to the top of the list.
另外,请注意,比较值的排序也将有助于提高性能,将最有可能遇到的值放在列表顶部附近。
ConfigDataType Lookup tab is defined as:
ConfigDataType查找选项卡定义为:
RowSource is a two column value list: 8;Text;3;Long;4;Single;5;Double;7;Date;11;Boolean
RowSource是两列值列表:8; Text; 3; Long; 4; Single; 5; D ouble; 7; Da te; 11; Bool ean
BoundColumn: 1
绑定列:1
ColumnWidths: 0";2"
列宽:0“; 2”
High performance version of the GetConfigSetting() function:
高性能版本的GetConfigSetting()函数:
'===================================================
'Performance tweaked version of the casting function
'===================================================
Public Function GetConfigSetting(parmConfigName As String) As Variant
Dim varValue As Variant
Dim lngType As Long
varValue = DLookup("ConfigValue", "ConfigurationSettings", "ConfigName = " & Delimed(parmConfigName))
If IsNull(varValue) Then
GetConfigSetting = vbNullString
Else
lngType = DLookup("ConfigDataType", "ConfigurationSettings", "ConfigName = " & Delimed(parmConfigName))
Select Case lngType
Case vbString
GetConfigSetting = CStr(varValue)
Case vbBoolean
GetConfigSetting = CBool(varValue)
Case vbLong
GetConfigSetting = CLng(varValue)
Case vbSingle
GetConfigSetting = CSng(varValue)
Case vbDouble
GetConfigSetting = CDbl(varValue)
Case vbDate
GetConfigSetting = CDate(varValue)
Case Else
GetConfigSetting = varValue
End Select
End If
End Function
If this article was helpful, please click the
YESlink below.
如果本文对您有所帮助,请单击下面的
“是”链接。
翻译自: https://www.experts-exchange.com/articles/1740/Introduction-to-Casting.html
铸造 编码规则