数据录入窗口的通用写法

数据录入窗口有很多公用程序,这里进行简单总结,然后读者可以考虑使用继承、用户对象等方式将这些公用内容封装起来,以便以后的开发中重用,从而提高软件的开发效率。公用程序总结以下几点:
1、插入
  通常提供一个命令按钮,在按钮的Clicked事件中编写如下脚本:
   dw_1.ScrollToRow(dw_1.InsertRow(0))
   2、删除
  通常提供一个命令按钮,在按钮的Clicked事件中编写如下脚本:
   integer li_flag
     long ll_CurRow

     ll_CurRow = dw_1.GetRow(0)
     if ll_CurRow < 1 then return

      li_Flag = MessageBox('提示','确实要删除当前数据吗?',Question!,YesNo!,2)
      if li_Flag = 1 then
         dw_1.DeleteRow(ll_CurRow)
      end if
   3、提供一个关闭按钮,在该按钮的Clicked事件上编写如下脚本:
    Close(parent)
    4、提供一个保存按钮,在该按钮的Clicked事件上编写如下脚本:
    Long ll_Rows

     ll_Rows = dw_1.ModifiedCount() + dw_1.DeletedCount()
     if ll_Rows < 1 then return
     if dw_1.Update() = 1 then
         commit;
         MessageBox('提示','数据保存成功。保存了' + String(ll_Rows) + '条记录。')
     else
         rollback;
         MessageBox('提示','数据错误,请仔细检查。')
       end if
     5、在数据窗口控件dw_1的Constructor事件中编写如下脚本:
      This.SetTransObject(SQLCA)
        在DBError事件中编写如下脚本:
       return 1
          在ItemError事件中编写如下脚本:
       return 1
          在LoseFocus事件中编写如下脚本:
       This.AcceptText()
       6、在窗口的CloseQuery事件中编写如下脚本:
integer li_flag
long ll_Rows
dw_1.AcceptText()
ll_Rows = dw_1.ModifiedCount() + dw_1.DeletedCount()
if ll_Rows > 0  then
li_flag = MessageBox('提示','数据已经修改,是否保存?',&
                           Question!,YesNoCancel!,1)
choose case li_flag
case 1  //保存
  if dw_1.Update() = 1 then
   commit;
       return 0
  else
   if MessageBox('提示','数据错误,不能保存。是否继'+&
            '续关闭?',Question!,YesNo!,2) = 1 then
    return 0
   else
    rollback;
    return 1
   end if
  end if
case 2  //不保存
  rollback;
  return 0
case 3  //取消
  return 1
end choose
else
return 0
end if
<think>我们被要求编写一个提取字符串的子程序。参考引用中提供了一个示例:使用过滤字符串函数,但实际我们可能需要更通用的方法。 在易语言中,我们可以通过循环逐个判断字符并提取符合要求的字符来实现。 以下是一个通用的子程序,用于从字符串中提取指定类型的字符(例如只保留字母、只保留数字等)。 我们将编写一个名为“提取字符串”的子程序,它接受三个参数: 1. 待处理的字符串 2. 要保留的字符类型(可选,例如:字母、数字、字母和数字等,可以用标志位或字符串参数指定) 3. 或者更灵活:我们可以通过一个自定义的字符集字符串来指定要保留的字符(例如:"a-zA-Z0-9"表示字母和数字,或者直接列出所有允许的字符) 但是,易语言本身没有内置类似正则表达式的字符类功能(如"a-z"表示所有小写字母),所以我们可以设计一个简单的字符集描述方式,或者直接让用户提供允许的字符列表。 为了简化,这里我们提供两种方式: 方式1:通过一个文本参数指定允许的字符(例如,如果允许所有字母,则传入"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 方式2:通过预定义的几个类型(如:1-字母;2-数字;3-字母和数字)来指定。 这里我们采用方式1,因为更灵活。 子程序:提取字符串 参数: 参数1:待处理的字符串,文本型 参数2:允许的字符集,文本型(例如:"abc"表示只保留a、b、c;"a-zA-Z"表示所有字母;我们也可以支持范围表示,但为了简化,我们先不支持范围,而是要求用户写出所有允许的字符。如果需要支持范围,我们可以再写一个解析范围的子程序) 但是,引用中提到了一个过滤字符串函数,其第二个参数是"a-zA-Z",所以我们可以考虑支持这种范围表示法。 因此,我们需要先解析允许的字符集字符串,将其转换为一个字符集合(即一个文本,包含所有允许的单个字符)。然后遍历待处理字符串,检查每个字符是否在允许的字符集中。 步骤: 1. 将允许的字符集字符串解析为实际允许的字符集合(比如将"a-zA-Z"解析为包含所有大小写字母的字符串) 2. 遍历待处理字符串的每个字符 3. 如果当前字符在解析后的字符集合中,则将其添加到结果字符串 4. 返回结果字符串 但是,解析字符集字符串是一个复杂的过程,我们可以先实现一个解析范围的方法。 注意:我们考虑字符集字符串中可能包含普通字符和用连字符表示的范围(例如:a-z表示从a到z的所有字符)。但要注意,如果连字符出现在开头或结尾,则它只是普通字符。另外,如果连续出现两个连字符,则中间的部分可能是一个范围(但这样写不标准,我们按标准的方式:一个连字符连接两个字符表示一个范围)。 我们可以这样设计解析规则: 遍历字符集字符串的每个字符,同时维护一个状态,当遇到连字符且前后都是字符时,将连字符解释为范围符号,否则将连字符当作普通字符。 但是,为了简化,我们可以采用以下步骤: 1. 创建一个空的结果字符串(用于存储所有允许的字符) 2. 创建一个变量,用于存储当前是否处于范围解析状态(即上一个字符是一个普通字符,当前遇到连字符,下一个字符是结束字符) 3. 遍历字符集字符串的每个位置(索引从1到取文本长度): 如果当前字符是连字符('-')并且它不在开头和结尾,并且它的前一个字符和后一个字符都是可打印字符(且前一个字符的ASCII码小于后一个字符),那么我们就将这两个字符之间的所有字符添加到结果字符串中。 否则,将当前字符当作普通字符添加到结果字符串(如果当前字符是连字符且不符合范围条件,则直接添加)。 但是,这样处理可能会重复添加字符(比如允许的字符集中有重复字符),我们可以考虑使用一个逻辑变量数组(但易语言中处理字符集可能不太方便)或者使用一个文本变量,然后去重。 然而,去重操作可能会增加复杂度,而且字符集通常不会太大,所以我们可以允许结果字符串中有重复字符,然后在判断时不会有影响(因为一个字符只要在结果字符串中出现一次就算允许)。 但是,为了效率,我们可以不去重,因为重复字符不会影响判断结果。 另一种思路:我们不在解析时展开范围,而是在判断每个字符时,检查它是否在某个允许的范围内。但这样每次判断都要遍历整个字符集字符串(包含范围表达式),效率较低。 因此,我们选择在解析时展开范围,生成一个包含所有允许字符的字符串(即一个字符集合字符串)。 具体实现: 子程序:解析字符集 参数:字符集表达式(文本型) 返回:展开后的字符集合(文本型) 步骤: 初始化一个空字符串:strAllowed 初始化一个变量:i,从1循环到取文本长度(字符集表达式) 当前字符:c = 取文本中间(字符集表达式, i, 1) 如果 i < 取文本长度(字符集表达式)-1 且 取文本中间(字符集表达式, i+1, 1) = '-' 且 i+2<=取文本长度(字符集表达式) 那么,我们遇到了一个范围:start = c, end = 取文本中间(字符集表达式, i+2, 1) 然后,将start到end之间的所有字符添加到strAllowed(包括start和end) 然后,i = i+2 ' 跳过接下来的连字符和结束字符 否则 将c添加到strAllowed 返回 strAllowed 但是,这种处理方式无法处理连续的范围,比如"a-zA-Z0-9",因为它会跳过中间的字符。所以我们需要更严谨的解析。 实际上,我们可以这样: 遍历索引i,从1到取文本长度(字符集表达式): 如果当前字符是连字符,并且它的前面有字符(i>1)并且后面有字符(i<取文本长度(字符集表达式)),那么: 前一个字符:prev = 取文本中间(字符集表达式, i-1, 1) 后一个字符:next = 取文本中间(字符集表达式, i+1, 1) 如果prev和next都是同类型的字符(比如都是小写字母,或都是大写字母,或都是数字),并且prev的ASCII码小于next的ASCII码,那么: 将prev到next之间的所有字符(包括prev和next)添加到strAllowed(注意:prev已经在上一次循环中添加过了,所以这里从prev+1开始到next) 然后,我们跳过这个连字符和后面的next(即i增加1,这样下一个循环会从next的下一个字符开始)?但是这样会跳过next,所以我们需要在添加范围后,将i增加1(这样下一次循环会跳过next,因为next已经被处理了) 否则,将当前字符(连字符)当作普通字符加入。 否则,将当前字符加入。 但是,这样处理需要回溯前一个字符,而且前一个字符可能已经被加入,所以我们要避免重复添加。 因此,我们可以改变思路:在解析字符集表达式时,我们使用一个状态变量,记录前一个字符,然后当遇到连字符时,检查下一个字符,如果符合条件,就添加范围,否则添加前一个字符和连字符。 我们采用逐个字符处理,并考虑前一个字符和下一个字符。 具体步骤(使用循环): 初始化:strAllowed = "" i = 1 当 i <= 取文本长度(字符集表达式) 时: 当前字符:c = 取文本中间(字符集表达式, i, 1) 如果 c = '-' 且 i>1 且 i<取文本长度(字符集表达式) : 前一个字符:prev = 取文本中间(字符集表达式, i-1, 1) 后一个字符:next = 取文本中间(字符集表达式, i+1, 1) 如果 prev 和 next 都是同类型(比如都是字母或都是数字)且 字符编码(prev) < 字符编码(next): 则从 prev+1 到 next 的所有字符添加到strAllowed(因为prev已经在上一步被添加过了,所以这里只需要添加prev+1到next) 然后 i = i+2 # 跳过连字符和next,因为next会被添加 否则: 将当前字符(连字符)添加到strAllowed i = i+1 否则: 将c添加到strAllowed i = i+1 但是,这种方法会漏掉prev后面的连字符和next,而且我们并没有在之前添加prev,所以我们需要在遇到非连字符时添加,而遇到连字符时则根据情况处理。 因此,我们调整:在循环中,每个字符如果不是连字符,就直接添加。当遇到连字符时,检查它是否构成范围,如果构成,则添加范围(从prev+1到next)并跳过下一个字符(next),否则添加连字符。 但是,这样prev已经被添加过了(因为prev是前一个字符,我们在上一个循环中添加了它),所以当我们遇到连字符时,prev已经在strAllowed中,所以我们只需要添加从prev+1到next的字符。 注意:如果连字符在开头,则它只是普通字符;在结尾同理。 因此,我们这样实现: 子程序:解析字符集 参数:字符集表达式(文本型) 返回:展开后的字符集合(文本型) 步骤: strAllowed = "" i = 1 len = 取文本长度(字符集表达式) ' 先处理第一个字符(如果存在) 如果 len>0 则 如果 取文本中间(字符集表达式,1,1) ≠ "-" 则 strAllowed = strAllowed + 取文本中间(字符集表达式,1,1) i = 2 循环判断 i <= len c = 取文本中间(字符集表达式, i, 1) ' 如果当前字符是连字符,并且不是第一个字符,也不是最后一个字符 如果 c = "-" 且 i < len 且 i > 1 则 prev = 取文本中间(字符集表达式, i-1, 1) ' 前一个字符(已经添加过了) next_char = 取文本中间(字符集表达式, i+1, 1) ' 检查prev和next_char是否构成有效的范围(prev<next_char) 如果 取代码(prev) < 取代码(next_char) 则 ' 添加从prev+1到next_char的所有字符 循环 j = 取代码(prev)+1 到 取代码(next_char) strAllowed = strAllowed + 字符(j) 循环结束 i = i+2 ' 跳过连字符和next_char 否则 strAllowed = strAllowed + c i = i+1 结束如果 否则 strAllowed = strAllowed + c i = i+1 结束如果 循环结束 返回 strAllowed 但是,这样处理会有一个问题:如果连续两个连字符,比如"--",那么第一个连字符会被当作普通字符(因为它的前一个字符不是连字符?),然后第二个连字符会被当作范围符号?所以我们需要考虑。 实际上,我们要求范围必须由两个非连字符字符和一个连字符构成,所以连续连字符不会构成范围。 但是,这样解析后,我们得到的strAllowed可能包含重复字符(比如字符集表达式为"a--z",那么解析后会有a,然后是两个连字符,然后是从a+1到z的字符,其中a又出现了?),但重复不影响使用。 然后,我们编写提取字符串的子程序: 子程序:提取字符串 参数: 待处理字符串,文本型 字符集表达式,文本型(可选,默认为空,表示不过滤) 返回:文本型 步骤: 1. 如果字符集表达式为空,则返回待处理字符串(或者如果字符集表达式有默认值,比如"a-zA-Z0-9",则按默认值处理) 2. 解析字符集表达式,得到允许的字符集合:strAllowed = 解析字符集(字符集表达式) 3. 初始化结果字符串:result = "" 4. 遍历待处理字符串的每个字符: 当前字符 c = 取文本中间(待处理字符串, i, 1) 如果 c 在 strAllowed 中(即寻找文本(strAllowed, c, , 假) > 0),则 result = result + c 5. 返回 result 注意:在易语言中,寻找文本函数可以用于检查一个字符是否在字符串中出现。 但是,这种方法对于中文字符可能有效,因为中文字符也是作为文本处理的。但要注意,易语言中一个中文字符占两个字节,但这里我们按字符处理,易语言的取文本中间是按字符位置(不是字节位置)处理的。 因此,我们编写代码: 注意:由于易语言中字符处理是按字节还是按字符?实际上,在易语言中,文本函数都是基于字符的(一个英文字符和一个中文字符都是一个字符),所以上述方法同样适用于中文字符。 但是,在解析字符集表达式时,如果包含中文字符,那么范围表示(如"一-龥")表示所有中文字符?但是中文字符的编码是连续的(在GBK中并不连续),所以这种方法对中文字符的范围可能不适用。因此,我们建议在字符集表达式中不要对中文字符使用范围表示,而是直接列出所有中文字符,或者使用其他方法。 因此,我们限制:字符集表达式只适用于单字节字符(即ASCII字符)的范围,对于双字节字符(如汉字),我们只能单独列出。 考虑到易语言的实际应用,我们通常只需要处理英文字母和数字,所以这个限制可以接受。 现在,我们编写代码: 注意:易语言中取代码()函数返回的是字符的ASCII码(对于汉字,返回的是汉字内码的第一个字节,所以不适用)。因此,我们只对ASCII字符使用范围展开,对于汉字,我们直接将其加入允许字符集(即不展开范围)。 所以,我们修改解析字符集的步骤:在判断范围时,先判断prev和next_char是否都是单字节字符(即ASCII码在0~127之间),如果不是,则不当作范围处理。 修改上述解析步骤中的条件: 如果 c = "-" 且 i < len 且 i > 1 且 取代码(prev) <= 127 且 取代码(next_char) <=127 且 取代码(prev) < 取代码(next_char) 则 ...展开范围 否则 ...当作普通字符 这样,如果遇到中文字符,就不会被当作范围处理,而是直接添加连字符或中文字符。 下面我们编写具体的易语言代码: 由于代码较长,我们分两个子程序:解析字符集 和 提取字符串 注意:在易语言中,字符的ASCII码可以通过 取代码() 函数得到,而字符可以通过 字符() 函数由ASCII码得到。 另外,我们还需要注意:在解析字符集时,如果遇到范围,我们添加的是从prev+1到next_char的字符,因为prev已经在上一步被添加过了(在循环中,prev是在上一次循环中作为普通字符添加的)。 但是,我们在循环中处理第一个字符时,已经单独处理了。然后从第二个字符开始循环,所以每个字符都是作为普通字符添加的,直到遇到连字符并满足条件时,才添加范围并跳过下一个字符。 因此,我们编写代码:</think>### 易语言字符串提取子程序实现 在易语言中提取字符串的子程序可以通过多种方式实现,下面我将详细介绍两种常用方法:基于字符遍历的提取方法和使用正则表达式的高级方法。 #### 方法1:基础字符遍历法(推荐) ```vb .版本 2 .子程序 提取字符串, 文本型 .参数 原始文本, 文本型 .参数 提取类型, 整数型, 可空, 1=数字 2=字母 3=汉字 4=自定义(默认) .参数 自定义字符集, 文本型, 可空, 当提取类型=4时有效 .局部变量 结果文本, 文本型 .局部变量 i, 整数型 .局部变量 当前字符, 文本型 .局部变量 字符代码, 整数型 .判断开始 (是否为空 (提取类型)) 提取类型 = 4 .判断结束 .计次循环首 (取文本长度 (原始文本), i) 当前字符 = 取文本中间 (原始文本, i, 1) 字符代码 = 取代码 (当前字符, ) .判断开始 (提取类型 = 1) ' 提取数字 .如果真 (字符代码 ≥ 48 且 字符代码 ≤ 57) 结果文本 = 结果文本 + 当前字符 .如果真结束 .判断 (提取类型 = 2) ' 提取字母 .如果真 ((字符代码 ≥ 65 且 字符代码 ≤ 90) 或 (字符代码 ≥ 97 且 字符代码 ≤ 122)) 结果文本 = 结果文本 + 当前字符 .如果真结束 .判断 (提取类型 = 3) ' 提取汉字 .如果真 (字符代码 > 127) 结果文本 = 结果文本 + 当前字符 .如果真结束 .默认 ' 自定义字符集 .如果真 (寻找文本 (自定义字符集, 当前字符, , 假) > 0) 结果文本 = 结果文本 + 当前字符 .如果真结束 .判断结束 .计次循环尾 () 返回 (结果文本) ``` #### 方法2:正则表达式法(需易语言支持库) ```vb .版本 2 .支持库 RegEx .子程序 正则提取字符串, 文本型 .参数 原始文本, 文本型 .参数 模式, 文本型, , 正则表达式模式 .局部变量 正则, 正则表达式 .局部变量 结果, 搜索结果 .局部变量 结果文本, 文本型 正则.创建 (模式, ) 结果 = 正则.搜索 (原始文本) .判断循环首 (结果.是否匹配 ()) 结果文本 = 结果文本 + 结果.取匹配文本 (原始文本, ) 结果 = 正则.继续搜索 () .判断循环尾 () 返回 (结果文本) ``` #### 使用示例 ```vb .版本 2 .子程序 __启动窗口_创建完毕 .局部变量 测试文本, 文本型 .局部变量 结果, 文本型 测试文本 = "Hello 世界! 123 ABC" ' 示例1:提取所有字母 结果 = 提取字符串 (测试文本, 2, ) 信息框 ("提取字母: " + 结果, 0, "结果", ) ' 显示: HelloABC ' 示例2:提取所有数字 结果 = 提取字符串 (测试文本, 1, ) 信息框 ("提取数字: " + 结果, 0, "结果", ) ' 显示: 123 ' 示例3:提取自定义字符 结果 = 提取字符串 (测试文本, 4, "H世!") 信息框 ("自定义提取: " + 结果, 0, "结果", ) ' 显示: H世! ' 示例4:使用正则表达式提取 结果 = 正则提取字符串 (测试文本, "[A-Z]+") 信息框 ("正则提取大写字母: " + 结果, 0, "结果", ) ' 显示: HABC ``` ### 关键点解析 1. **字符编码识别**: - 数字:ASCII 48-57 (`0-9`) - 大写字母:ASCII 65-90 (`A-Z`) - 小写字母:ASCII 97-122 (`a-z`) - 汉字:编码 > 127 (GBK编码) 2. **自定义字符集**: - 使用`寻找文本()`函数检查字符是否在自定义集合中 - 支持任意字符组合,如标点符号、特殊字符等 3. **正则表达式扩展**: - `[0-9]+` 匹配连续数字 - `[a-zA-Z]+` 匹配连续字母 - `[\u4e00-\u9fa5]` 匹配汉字(需Unicode支持) 4. **性能优化**: - 对于长文本,使用`快速文本对象`代替字符串拼接 - 使用`指针操作`提高大文本处理效率 - 预编译正则表达式模板复用[^1] ### 应用场景 1. 数据清洗:从混合文本中提取有效数据 2. 格式验证:检查输入是否符合特定格式 3. 文本分析:统计特定字符出现频率 4. 安全过滤:移除非法字符
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值