public prikey '表的主键 public tableName '表名 public auto_ '自动填充 public validate_ '自动验证 Public db_type,access_type,db_path,db_host,db_user,db_name,db_pwd Public patchValidate '是否批处理验证 public [error] '最近错误消息 public pageSize '默认每页取多少条记录 public Version '版本号 Public isOnlySql '是否只获取sql语句 Public tool 'POPASP_DATABASE_TOOL实例 Private options '存储分配过来的参数,Dictionary对象 Private parsedOptions '存储解析后的参数,Dictionary对象 Private lastSql '存储最后一条sql语句,String Private ConnStr '数据库连接字符串 Private dTables '存储已经取出的所有的数据表 Private dTS '存储数据表的结构,为dTableStructrues的简写 public isTest Public Function getLastSql() getLastSql = lastSql End Function '获取parsedOptions("data") Public Function getData() if isObject( parsedOptions("data") ) then set getData = parsedOptions("data") else getData = parsedOptions("data") end if end Function ' slect Public Function [Select] () call parseOptions lastSql = getSelectSql(parsedOptions) if isOnlySql then [Select] = lastSql : Exit Function set [Select] = tool.Select(lastSql,parsedOptions,Me.pageSize) call ResumeOpts End Function ' find Public Function Find() call parseOptions lastSql = getFindSql( parsedOptions ) if isOnlySql then Find = lastSql : Exit Function set Find = tool.Find( lastSql ) call ResumeOpts End Function '获取字段值,如果fields为"",则取field方法fieldRev中的值 '取一个字段的值,如果分配多个,只取第一个,取多个字段的值请使用getFields Public Function getField(fields) call field( fields ) call parseOptions lastSql = getFindSql( parsedOptions ) if isOnlySql then getField = lastSql : Exit Function getField = tool.getField( lastSql ) call ResumeOpts End Function '获取字符值,如果fields为"",则取field方法fieldRev中的值 '返回数据为Dictionary对象 Public Function getFields(fields) call field( fields ) call parseOptions lastSql = getFindSql( parsedOptions ) if isOnlySql then getFields = lastSql : Exit Function set getFields = tool.getFields( lastSql ) call ResumeOpts End Function '获取二维Dictionary对象 Public Function getAll() dim rs set rs = Me.select set getAll = POP_MVC.rs2dict(rs) Call tool.closeRS(rs) End Function '通过连贯操作,从数据表中随机取出num行记录,返回二维Dictionary对象 'sort值分三种,0:打乱的顺序,-1:逆序,1:顺序 Public Function getRand( byval arg ) dim rs : set rs = [Select]() dim arr,dict,cnt,curRand,total,i,sort,num sort = 0 if isArray( arg ) then if ubound( arg ) > 0 then sort = arg(1) end if num = arg(0) else num = arg end if if isOnlySql then getRand = lastSql : Exit Function if rs.recordCount <= num then set getRand = POP_MVC.rs2dict( array(rs) ) else arr = array() cnt = 0 total = rs.recordCount Randomize Do Until cnt >= num curRand = CLng((Rnd*(total-1))+1) if not POP_MVC.Arr.Exists( arr,curRand ) Then POP_MVC.Arr.Push arr,curRand cnt = cnt + 1 end if Loop if sort > 0 then Call POP_MVC.Arr.sort(arr) set dict = D_ elseif sort < 0 then Call POP_MVC.Arr.rsort(arr) set dict = D_ end if '不要将取数据与取随机数合并,这样做更省时 for i = 0 to ubound(arr) rs.AbsolutePosition =arr(i) POP_MVC.Dict.Push dict,"",Me.getRow(rs) next set getRand = dict end if End Function '从Recordset对象中取出一行,返回Dictionary对象 Public Function getRow( rs ) set getRow = tool.getRow( rs ) End Function ' 定位查询,获取第N条记录,返回Dictionary对象 ' num正数从0开始计,负数则-1表示最后1条 Public Function getN( num ) dim rs : set rs = [Select]() if isOnlySql then getN = lastSql : Exit Function set getN = tool.getN( rs , num ) End Function ' 获取第一条记录,返回Dictionary对象 Public Function First() dim rs : set rs = [Select]() if isOnlySql then First = lastSql : Exit Function set First = tool.First(rs) end Function ' 获取最后一条记录,返回Dictionary对象 Public Function Last() dim rs : set rs = [Select]() if isOnlySql then Last = lastSql : Exit Function set Last = tool.Last(rs) end Function ' count计数 Public Property Get Count() Count = Statistics( "0" , "COUNT") End Property ' Max取最大值 Public Property Get Max( field ) Max = Statistics(field , "MAX") End Property ' Min取最小值 Public Property Get Min( field ) Min = Statistics(field , "MIN") End Property ' Avg取平均值 Public Property Get Avg( field ) Avg = Statistics(field , "AVG") End Property ' Sum求和 Public Property Get Sum( field ) Sum = Statistics(field , "SUM") End Property Public Function Statistics( ByVal oneField, ByVal stat ) '去掉多余的`[] oneField = POP_MVC.String.trim(oneField,"`") oneField = POP_MVC.String.ltrim(oneField,"[") oneField = POP_MVC.String.rtrim(oneField,"]") if not isNumeric(oneField) then if tool.isMicroDB then oneField = "[" & oneField & "]" else oneField = "`" & oneField & "`" end if end if call field( stat & "( " & oneField & " ) as popasp_result") call parseOptions lastSql = getFindSql( parsedOptions ) if isOnlySql then Statistics = lastSql : Exit Function Statistics = tool.Statistics( lastSql , stat ) call ResumeOpts End Function ' mode为1时新增,2时修改,3时新增/修改 Public Property Get Create( mode ) On Error Resume Next dim key,data call parseOptions '解析参数 Create = false if isEmpty( parsedOptions("data") ) Then set parsedOptions("data") = POP_MVC.Form2Dict() end If set data = parsedOptions("data") call AutoComplete( parsedOptions("data") , mode ) if not AutoValidate( data , mode ) Then Create = False exit Property End If if isEmpty( parsedOptions("data") ) then set parsedOptions("data") = data end if Create = true call L_( Me.db_type & " Create" ) End Property ' 字段增长 比如传参"views",相当于 views = views + 1 ' 传参数组,比如 array("views",3),相当于 views = views + 3 ' 只能处理一个字段的值 Public Property Get SetInc( arg ) SetInc = SetIncOrDec( arg, "+" ) end Property ' 字段增长 比如传参"views",相当于 views = views + 1 ' 传参数组,比如 array("views",3),相当于 views = views + 3 ' 只能处理一个字段的值 Public Property Get SetDec( arg ) SetDec = SetIncOrDec( arg, "-" ) end Property ' 字段取反 比如传参"top",相当于 top = Abs( Not top ) ' 传参数组,比如 array("top","rmp"),相当于 top = Abs( Not top ),rmp = Abs( Not rmp ) ' 字符串传多个参数,比如"top,rmp",相当于 top = Abs( Not top ),rmp = Abs( Not rmp ) Public Property Get SetNot( arg ) dim arr,i,str if typeName(arg) = "String" then arr = split( arg , "," ) elseif isArray( arg ) then arr = arg end if if isArray( arr ) then str = "" for i = 0 to ubound( arr ) str = str & arr(i) & " = Abs( Not " & arr(i) & " ) , " next str = POP_MVC.String.rtrim( str , ", " ) SetNot = SetField( array("exp", str ),"" ) end if end Property '多个字符用英文逗号分隔 Private Function SetIncOrDec( ByVal arg , ByRef operator ) dim arr,i,str if typeName(arg) = "String" then arg = array(arg) if isArray( arg ) then if ubound( arg ) = 0 then POP_MVC.Arr.Push arg , 1 end if if is_numeric(arg(1)) then arr = split( arg(0) , "," ) str = "" for i = 0 to ubound( arr ) str = str & arr(i) & " = " & arr(i) & " " & operator & " " & arg(1) & " , " next str = POP_MVC.String.rtrim( str , ", " ) SetIncOrDec = SetField( array("exp", str ),"" ) end if end if End Function '修改字段的值 'field如果为字符串,则在数据表中设置 set field = value '如果为dictionary对象,则设置 set key1 = val1,key2 = val2,……。此时的value值不起作用,可以随便给个值 Public Function SetField( field,value ) dim stype: stype = typeName(field) dim dict if tool.dataIsExp(field) OR stype = "Dictionary" then Call data( field ) SetField = Save() elseif stype = "String" Then set dict = D_ dict(field) = value call data(dict) SetField = Save() set dict = nothing else call POP_MVC.error( Me.db_type & ".SetField") End If End Function ' 将两个ID的相应字段进行交换 ' eg. db.where("2,5").fields("...").swap() Public Property Get Swap() On Error Resume Next dim arr,dict1,dict2,rs '如果未进行where赋值,报错并退出 if isEmpty( options("where") ) Then call ResumeOpts call POP_MVC.warning( Me.db_type & ".Swap 未进行交换ID赋值") Exit Property End if arr = options("where") set options("where") = nothing '如果分配的是字符串,用逗号将其炸开 If typename( arr ) = "String" then arr = split( arr , "," ) arr(0) = trim( arr(0) ) arr(1) = trim( arr(1) ) end if '必须是Array,且只能有两个ID if isArray( arr ) then '如果不是两个元素 if ubound( arr ) <> 1 then call ResumeOpts call POP_MVC.warning( Me.db_type & ".Swap 有且只能有两个ID") Exit Property end if '如果两个ID不是数值表达形式 if not is_numeric( arr(0) ) OR not is_numeric( arr(1) ) then call ResumeOpts call POP_MVC.warning( Me.db_type & ".Swap 交换ID必须是数字") Exit Property end if else call ResumeOpts call POP_MVC.warning( Me.db_type & ".Swap ID分配错误") Exit Property end if '获取第1个ID的字段值 options("where") = arr(0) set rs = Me.find() '第一个用find获取,可以兼顾db.field与db.fieldRev set dict1 = POP_MVC.rs2dict( rs ) rs.close set rs = nothing '获取第2个ID的字段值 options("where") = arr(1) set dict2 = Me.getFields( dict1.keys ) '第二个用getFields获取,则与第一个有相同字段 '将第2个ID的字段值给第1个ID options("where") = arr(0) Swap = Me.setField( dict2,null ) set dict2 = nothing if Swap > 0 then '将第1个ID的字段值给第2个ID options("where") = arr(1) Swap = Me.setField( dict1,null ) set dict1 = nothing end if Call L_( Me.db_type & ".Swap" ) End Property ' 修改数据,根据sql修改 Public Property Get Save() On Error Resume Next dim popts,pk,ts call parseOptions '解析参数 set popts = parsedOptions if is_empty(popts("table")) then Call setPoptsTable( popts ) end if if isEmpty( parsedOptions("data") ) Then set parsedOptions("data") = POP_MVC.Form2Dict() end If if ( not is_empty( popts("data") )) Then isTest = 1 pk = getPrikey( POP_MVC.String.rtrim(popts("table"),"$")) popts("table") = getTableFromInput( popts("table") ) if pk<>"" AND isEmpty( popts("where") ) Then if tool.isDbType("excel") then set ts = getTableStructure(popts("table")) If (Not isEmpty( popts("data")(pk) )) Then popts("where") = "[" & pk & "] = " & tool.getSqlStr( ts(pk),popts("data")(pk) ) elseif tool.isMicroDB() then If (Not isEmpty( popts("data")(pk) )) Then popts("where") = "[" & pk & "] = " & popts("data")(pk) else If (Not isEmpty( popts("data")(pk) )) Then popts("where") = "`" & pk & "` = " & popts("data")(pk) end if End If if Not isEmpty( popts("where") ) Then if pk<>"" and typename( popts("data") ) = "Dictionary" Then if popts("data").Exists( pk ) AND popts("data").count > 1 then Call popts("data").Remove( pk ) end if End If lastSql = getUpdateSql(popts) if isOnlySql then Save = lastSql : Exit Property Save = tool.Save( lastSql ) else call POP_MVC.exit( "在你的修改操作中未发现where或ID限制条件,不含限制的修改操作被禁用!!" ) End If else call POP_MVC.error( Me.db_type & ".Save") end If call ResumeOpts End Property ' 删除数据 Public Property Get Remove() call parseOptions '解析参数 Call setPoptsTable( parsedOptions ) if tool.isDbType("excel") Then '对于Excel不能真删除,只能将各个字段值设为null Remove = DeleteBySql( parsedOptions("table"),parsedOptions("where") ) else lastSql = getDeleteSql(parsedOptions) if isOnlySql then Remove = lastSql : Exit Property Remove = tool.Remove(lastSql,parsedOptions) call ResumeOpts end if End Property ' 更改记录,data为Dictionary对象,其键名与字段名相对应 Public Function Update(ByVal table,ByVal data,ByVal where) dim pk,ts table = getTableFromInput(table) call handlerData( table,data,0 ) '剔除不存在的字段 pk = getPrikey(table) '获取主键 if is_empty(where) then '如果where为空 if pk<>"" AND data.Exists( pk ) then if tool.isDbType("excel") then set ts = getTableStructure(table) where = "[" & pk & "] = " & tool.getSqlStr( ts(pk),data(pk) ) elseif tool.isMicroDB() then where = "[" & pk & "] = '" & data( pk ) & "'" else where = "`" & pk & "` = '" & data( pk ) & "'" end if end if else where = getWhere( table,where ) end if if where <> "" then lastSql = "UPDATE " & table & " (采用Recordset更新) " & " WHERE " & where else lastSql = "UPDATE " & table & " (采用Recordset更新) " end if if isOnlySql then Update = lastSql : Exit Function Update = tool.Update( table,data,where,pk ) 'tool.update已经考虑where为空的报错 End Function ' 删除记录,一定要输入where Public Function Delete(table,where) table = getTableFromInput(table) where = getWhere( table,where ) if tool.isDbType("excel") Then Delete = DeleteBySql( table,where ) else if where <> "" then lastSql = "DELETE FROM " & table & " WHERE " & where else lastSql = "DELETE FROM " & table end if if isOnlySql then Delete = lastSql : Exit Function Delete = tool.Delete( table,where ) end if End Function ' 执行sql语句,适用于update、delete,如果要添加数据,最好使用insert,可以返回最后生成的ID ' 该函数还不太完善 Public Property Get Execute( sql ) lastSql = sql Execute = tool.Execute( sql ) End Property ' 根据类变量tableName来获取主键 Public Function getPK() getPK = getPrikey(tableName) End Function '根据SQL获取结果集 Public Function getRS(sql) lastSql = sql set getRS = tool.getRS(sql) End Function ' 获取主键,如果分配了主键,则取该值,否则返回第一个字段 Public Function getPrikey( byval table_name ) if tool.isDbType("excel") Then table_name = POP_MVC.String.rtrim( table_name,"$" ) if POP_MVC.String.iEqual(tableName,table_name) AND not isEmpty( prikey ) Then getPrikey = prikey else call getTableStructure(table_name) getPrikey = tool.getPrikey( table_name,dTS ) if tableName = table_name then prikey = getPrikey end if end if End Function Public Function getSelectSql( byref popts ) getSelectSql = tool.getSelectSql( popts ,tableName , getTableStructure(tableName) ) End Function 'DELETE FROM `post` WHERE post_id>10 Public Function getDeleteSql( popts ) if Not isObject(popts) Then if popts = "" Then call parseOptions set popts = parsedOptions End if End If getDeleteSql = tool.getDeleteSql(popts) End Function Private Function getUpdateOrInsertSql( popts , mode) on error resume next dim data if Not isObject(popts) Then if popts = "" Then call parseOptions set popts = parsedOptions End if End If set data = popts("data") call handlerData( popts("table"),data , 0 ) set popts("data") = data if mode = "update" Then getUpdateOrInsertSql = tool.getUpdateSql( popts("table"), popts("data"), popts("where") , getTableStructure( popts("table") ) ) else getUpdateOrInsertSql = tool.getInsertSql( popts("table"), popts("data") , getTableStructure( popts("table") ) ) end if Call L_( Me.db_type & ".getUpdateOrInsertSql" ) End Function 'UPDATE `post` SET `title` = '测试3',`add_time` = #2016/6/28 9:57:20#,`is_display` = True WHERE post_id>10 Public Function getUpdateSql( popts ) getUpdateSql = getUpdateOrInsertSql( popts, "update" ) End Function Public Function getInsertSql( popts ) getInsertSql = getUpdateOrInsertSql( popts, "insert" ) End Function public function safe( str ) safe = tool.safe(str) end function ' mode为数据表中对应字段的类型,val为添加或修改的值 Private Function getSqlStr(mode,val) getSqlStr = tool.getSqlStr(mode,val) End Function '为了减轻类的重量,将ParseWhere方法中的代码单独写到了一个文件中 Public Function ParseWhere(opts) 'POPASP_REPLACE_CLASS_PARSEWHERE_POPASP' End Function Public Function ParseHaving( opts ) ParseHaving = ParseWhere(opts) End Function Public Function ParseField( opts ) ParseField = tool.ParseField( opts,getTableStructure(getTableFromOptions(opts)) ) End Function private function getTableFromOptions(opts) if not isEmpty( opts("table") ) and opts("table") <> "" then getTableFromOptions = opts("table") elseif not isEmpty( tableName ) and tableName <> "" then getTableFromOptions = tableName else call POP_MVC.error( db_type & ".getTableFromOptions") end if end function private Sub setOption(key,opts) POP_MVC.dict.edit options,key,opts End Sub Public Function onlySql( bool ) isOnlySql = (Not is_empty(bool) ) : set onlySql = Me End Function ' 设置表名,可链式操作 Public Function table( opts ) Call setOption("table",opts) : set table = Me End Function Public Function top( opts ) Call setOption("top",opts) : Set Top = Me End Function Public Function where( opts ) Call setOption("where",opts) : set where = Me End Function Public Function fieldRev( opts ) Call setOption("fieldRev",opts) : set fieldRev = Me end Function Public Function field( opts ) Call setOption("field",opts) : set field = Me End Function Public Function [auto]( opts ) Call setOption("auto",opts) : set [auto] = Me End Function Public Function validate( opts ) Call setOption("validate",opts) : set validate = Me End Function Public Function order( opts ) Call setOption("order",opts) : set order = Me End Function Public Function limit( opts ) Call setOption("limit",opts) : set limit = Me End Function Public Function group( opts ) Call setOption("group",opts) : set group = Me End Function Public Function data( opts ) if typename( opts ) = "Dictionary" then Call setOption("data", POP_MVC.Dict.Clone(opts) ) elseif typename( opts ) = "Recordset" then Call setOption("data", POP_MVC.rs2dict(opts) ) else Call setOption("data", opts ) end if set data = Me End Function Public Function having( opts ) Call setOption("having",opts) : set having = Me End Function Public Function page( opts ) Call setOption("page",opts) : set page = Me End Function '暂时只支持一层left join Public Function leftJoin( opts ) Call setOption("leftJoin",opts) : set leftJoin = Me End Function Public Function union( opts ) if typename(options) <> "Dictionary" then set options = POP_MVC.dict.Create() end if if not options.Exists("union") or typename(options("union") ) <> "Dictionary" then set options("union") = POP_MVC.dict.Create() end if options("union")( options("union").Count ) = opts set union = Me End Function Public Function unionAll( opts ) if typename(options) <> "Dictionary" then set options = POP_MVC.dict.Create() end if if not options.Exists("unionAll") or typename(options("unionAll") ) <> "Dictionary" then set options("unionAll") = POP_MVC.dict.Create() end if options("unionAll")( options("unionAll").Count ) = opts set unionAll = Me End Function '切换数据库 '文本型数据库可传入密码,若要传入密码,须传入数组Array( dbPath,password ) '服务器型数据库,无须再设密码,传入空字符串就行 Public Function db( dbPath ) if tool.isDbType( "excel" ) or tool.isDbType( "access" ) or tool.isDbType( "sqlite3" ) then if isArray( dbPath ) then if ubound( dbPath ) > 0 then call tool.SwitchDB( dbPath(0) , dbPath(1) ) else call tool.SwitchDB( dbPath(0), "" ) end if else call tool.SwitchDB( dbPath, "" ) end if else call tool.SwitchSqlDB( dbPath ) end if set db = Me end Function '解析查询条件,为了减轻类的重量,将parseOptions方法中的代码单独写到了一个文件中 Private Sub parseOptions 'POPASP_REPLACE_CLASS_PARSEOPTIONS_POPASP' End sub Public Sub ResumeOptions() set options = nothing : set options = POP_MVC.dict.Create() End Sub Public Sub ResumeParsedOptions() set parsedOptions = nothing : set parsedOptions = POP_MVC.dict.Create() End Sub ' 重置链接操作的参数,可链式操作 Public Function ResumeOpts() isOnlySql = False : call ResumeOptions : call ResumeParsedOptions : set ResumeOpts = Me End Function '自动验证 Public Function AutoValidate ( ByVal data,ByRef mode ) on error resume next dim s_valid if Not isEmpty( parsedOptions("validate") ) Then s_valid = parsedOptions("validate") ElseIf Not isEmpty( validate_ ) Then s_valid = validate_ End If P_( "POPASP_AUTOVALIDATE" ).tableName = tableName P_( "POPASP_AUTOVALIDATE" ).patchValidate = patchValidate AutoValidate = P_( "POPASP_AUTOVALIDATE" ).handle(s_valid,data,mode) [error] = P_( "POPASP_AUTOVALIDATE" ).error Call L_( Me.db_type & ".AutoValidate" ) End Function '自动完成 Public Sub AutoComplete( ByRef data, ByRef mode ) on error resume next dim s_auto if Not isEmpty( parsedOptions("auto") ) Then s_auto = parsedOptions("auto") ElseIf Not isEmpty( auto_ ) Then s_auto = auto_ End If call P_( "POPASP_AUTOCOMPLETE" ).handle(s_auto,data,mode) call L_( Me.db_type & ".AutoComplete" ) End Sub ' 设置表名 Private Sub setPoptsTable( ByRef popts ) call tool.setPoptsTable(popts,tableName) End Sub '处理 增/改 中的数据 'bRemovePk是否删除主键 Private Sub handlerData ( ByRef tableName, ByRef data , ByRef bRemovePk ) call tool.handlerData(getTableStructure( tableName ),data ) if not is_empty( bRemovePk ) then '剔除主键,2.4版本中增加 dim pk,pos,keys pk = getPrikey( tableName ) if not isEmpty( pk ) then keys = data.keys pos = POP_MVC.Arr.iSearch( keys,pk ) if pos > -1 then data.remove( keys(pos) ) end if end if end if End Sub '获取表名,如果参数为"",则取Me.tableName private function getTableFromInput( ByVal table ) if table = "" Then table = Me.tableName '如果为"",采用全局变量的表名 table = POP_MVC.trim(table,"`") table = POP_MVC.ltrim(table,"[") table = POP_MVC.rtrim(table,"]") getTableFromInput = table if tool.isDbType("excel") Then 'Excel的表名还要在后面加"$" getTableFromInput = getTableName(table) end if end function Private Function getWhere( table,where ) dim pk,ts if is_numeric(where) then pk = getPrikey(table) if pk<>"" then if tool.isDbType("excel") then set ts = getTableStructure(table) getWhere = pk & " = " & getSqlStr( ts(pk) , where ) else getWhere = pk & " = " & where end if end if else getWhere = parseWhere(where) end if End Function Private Sub Class_Terminate on error resume next set dTables = nothing set dTS = nothing tool.conn.close set tool = nothing End Sub Private Sub Class_Initialize db_type = LCase(POP_MVC.String.ltrim(typename(Me),"POPASP_")) access_type = C_("ACCESS_TYPE") db_path = C_("DB_PATH") db_name = C_("DB_NAME") db_host = C_("DB_HOST") db_user = C_("DB_USER") db_pwd = C_("DB_PWD") call ResumeOpts set dTS = POP_MVC.dict.Create() patchValidate = False pageSize = C_("PAGE_PAGESIZE") Call assignTool( db_type,access_type,db_path,db_host,db_user,db_name,db_pwd ) isOnlySql = false End Sub Public sub assignTool( db_type,access_type,db_path,db_host,db_user,db_name,db_pwd ) if db_type = "access" or db_type = "excel" or db_type = "sqlite3" then set tool = P_( array("database_tool" , db_type & "#" & db_path) ) else set tool = P_( array("database_tool" , db_type & "#" & db_name) ) end if tool.db_type = db_type tool.access_type = access_type tool.db_path = db_path tool.db_name = db_name tool.db_host = db_host tool.db_user = db_user tool.db_pwd = db_pwd version = tool.version end sub '搜索功能,q为搜索的字符串,fields为指定的搜索字段(多个用英文逗号分隔) 'fields不能用""或者*代替 function Search( q,fields ) dim dict,where_ set dict = Me.parseSearch( q,fields ) call parseOptions if not isEmpty( parsedOptions("where") ) then parsedOptions("where") = "( " & parsedOptions("where") & " ) AND " & dict( "sql" ) else parsedOptions("where") = dict( "sql" ) end if lastSql = getSelectSql(parsedOptions) if isOnlySql then Search = lastSql : Exit Function set Search = tool.Select(lastSql,parsedOptions,Me.pageSize) call ResumeOpts end function '解析搜索字符串,返回Dictionary对象 '比如搜索q="张三 李四",返回{ "operator": "AND", "sql": "( ( CMS_Content LIKE '%张三%' OR CMS_Tag LIKE '%张三%' ) AND ( CMS_Content LIKE '%李四%' OR CMS_Tag LIKE '%李四%' ) )", "option": [ "张三", "李四" ] } '搜索字符串中的空格会被当作and来查询 function parseSearch( q,fields ) dim strAnd,reg,str,arr_q,sqls,temp,options,ret,j strAnd = " + " '第1步,将查询字符串中的and与+,都替换为+ set reg = POP_MVC.reg reg.Global = true : reg.IgnoreCase = true : reg.MultiLine = false reg.Pattern = "\s+and\s+" str = reg.replace( q, strAnd ) reg.Pattern = "\s+\+\s+" str = reg.replace( str, strAnd ) ' 第2步,将查询字符串用+符号分解成数组,如果没有+,则生成一个元素的数组 arr_q = split( str , strAnd) ' 第3步,循环数组,是标签则不再分解,不是标签还要用空格炸开 arr_q = POP_MVC.Arr.Unique(arr_q) temp = Array() reg.Pattern = "\s+" for each item in arr_q item = reg.replace(item," ") temp = POP_MVC.Arr.Merge( temp,split( item," " ) ) next arr_q = temp arr_q = POP_MVC.Arr.Unique(arr_q) if not isArray( fields ) then fields = split( fields, "," ) end if for each item in arr_q item = trim(item) temp = array() for j = 0 to ubound( fields ) POP_MVC.Arr.push temp, " " & fields(j) & " LIKE '%" & item & "%' " next POP_MVC.Arr.Push sqls, " ( " & join( temp," OR " ) & " ) " POP_MVC.Arr.Push options,item next set ret = D_ if ubound(options) > 0 then ret("operator") = "AND" ret("sql") = "( " & join( sqls," AND " ) & " )" ret("option") = options else ret("operator") = "" ret("sql") = POP_MVC.Arr.shift(sqls) ret("option") = POP_MVC.Arr.shift(options) end if set parseSearch = ret end Function '连贯操作,将数据以表格的形式进行展示,表格的最后一行是分页 '界面粗糙,只可作为演示或者管理员临时修改数据使用 '例如: db.htmlTable() Public Function htmlTable( ) dim dict,rs,page If isEmpty( Options( "page" )) Then Call Me.Page( Array( null, C_( "PAGE_PAGESIZE" ) ) ) End If set rs = Me.Select page = P_( "POPASP_PAGE" )(rs).show set dict = P_("POPASP_TEMPLATE").rs2dict(rs) Call tool.closeRS(rs) HtmlTable = P_("POPASP_HTML").Table( dict,"","",page ) End Function '连贯操作,将数据以表格的形式进行展示,表格的最后一行是分页,表格的最右行是操作(修改|删除) '界面粗糙,只可作为演示或者管理员临时修改数据使用 '例如: db.field().where().htmlList( "save.asp" ) Public Function htmlList( save_asp ) dim dict,rs,page If isEmpty( Options( "page" )) Then Call Me.Page( Array( null, C_( "PAGE_PAGESIZE" ) ) ) End If set rs = Me.Select htmlList = P_("POPASP_AUTO").htmlList( rs , tableName ,save_asp ) Call tool.closeRS(rs) End Function '将查询数据下载为Excel表格 'style为数组或用英文逗号分隔的字符串,代表各字段类型 'filename为文件名,如果给"",则取当前表名 Public Sub Excel( style , filename ) dim dict set dict = Me.getAll() if filename = "" then if Me.tableName <> "" then filename = Me.tableName else filename = now() end if end if Call POP_MVC.Dict.Excel(dict,style,filename) End Sub '开启事务处理 Property Get [Begin] tool.Execute( Array("BEGIN TRANSACTION" , 0 , 0 ) ) End Property '执行事务处理 Property Get Commit tool.Execute( Array("COMMIT TRANSACTION" , 0 , 0 ) ) End Property '回滚事务处理 Property Get Rollback tool.Execute( Array("ROLLBACK TRANSACTION" , 0 , 0 ) ) End Property ' 向数据表中添加多条数据 ' data应该是一个二维Dictionary对象 ' 会自动剔除表中不存在的字段所对应的数据 ' 返回值:返回二维Dictionary对象没有成功添加进去的键名 Public Property Get mAdd() On Error Resume Next call parseOptions '解析参数 if is_empty(parsedOptions("table")) then Call setPoptsTable( parsedOptions ) end if dim key , i , dict , sql , startTime , arr , pk , keys , pos , maxID , bExcelInc , rs arr = Array() i = 0 pk = getPrikey( POP_MVC.String.rtrim(parsedOptions("table"),"$")) startTime = timer() '对于Excel要获取最大的ID值 if db_type = "excel" and not isEmpty( pk ) then sql = "SELECT max(" & pk & ") as popasp_result FROM [" & parsedOptions("table") & "]" & " WHERE NOT ISNULL([" & pk & "])" set rs = getRS(sql) if not rs.eof then maxID = rs( "popasp_result" ) else maxID = 0 end if tool.closeRS rs bExcelInc = true end if Call Me.Begin for each key in parsedOptions("data") set dict = parsedOptions("data")(key) if typeName( dict ) = "Dictionary" then call handlerData( parsedOptions("table"),dict, 0 ) '剔除不存在的字段 '剔除主键 if db_type <> "excel" and db_type <> "sqlite3" AND not isEmpty( pk ) then keys = dict.keys pos = POP_MVC.Arr.iSearch( keys,pk ) if pos > -1 then dict.remove( keys(pos) ) end if end if if bExcelInc then keys = dict.keys pos = POP_MVC.Arr.iSearch( keys,pk ) if pos < 0 then dict(pk) = maxID + i + 1 end if end if if dict.count > 0 then sql = tool.getInsertSql( parsedOptions("table"), dict , getTableStructure( parsedOptions("table") ) ) if tool.Execute( array(sql , 0 , 0) ) then i = i + 1 else POP_MVC.Arr.Push arr,key end if else POP_MVC.Arr.Push arr,key end if else POP_MVC.Arr.Push arr,key end if next Call Me.Commit call POP_MVC.pushTime( startTime , "批量添加 " & i & "条数据" ) lastSql = sql mAdd = arr End Property ' 在数据表中批量修改N条数据,每条数据必须得含有主键,否则不予修改 ' data应该是一个二维Dictionary对象 ' 会自动剔除表中不存在的字段所对应的数据 ' 返回值:返回二维Dictionary对象没有成功修改的每条数据的ID值,注意跟mAdd返回值不同 Public Property Get mSave() On Error Resume Next call parseOptions '解析参数 if is_empty(parsedOptions("table")) then Call setPoptsTable( parsedOptions ) end if dim key , i , dict , sql , pk , startTime , temp , arr , keys , pos arr = Array() i = 0 pk = getPrikey( POP_MVC.String.rtrim(parsedOptions("table"),"$")) startTime = timer() Call Me.Begin for each key in parsedOptions("data") set dict = parsedOptions("data")(key) if typeName( dict ) = "Dictionary" then call handlerData( parsedOptions("table"),dict , 0 ) '剔除不存在的字段 keys = dict.keys pos = POP_MVC.Arr.iSearch( keys,pk ) if pos > -1 then temp = dict( keys(pos) ) dict.remove( keys(pos) ) if dict.count > 0 then sql = tool.getUpdateSql( parsedOptions("table"), dict , pk & " = " & temp , getTableStructure( parsedOptions("table") ) ) if tool.Execute( array(sql , 0 , 0) ) then i = i + 1 else POP_MVC.Arr.Push arr,temp end if else POP_MVC.Arr.Push arr,temp end if end if end if next Call Me.Commit call POP_MVC.pushTime( startTime , "批量修改 " & i & " 条数据" ) lastSql = sql mSave = arr End Property