|
|
楼主 |
发表于 2026-5-31 06:41:06
|
显示全部楼层
本帖最后由 likeyouli 于 2026-5-31 11:17 编辑
在python中获取剪贴板的内容,才是最高效的。但获取后要转为列表,通过json转列表,才最高效。
Sub 生成Python数据建表及导入_通过json转列表_仅有1列仅能通过eval转列表()
Dim oShell As Object, psCommand As String, i As Long, filepath3 As String, zhaodao As Range
filepath4 = "c:\create.py"
filepath5 = "c:\shuju.py"
MsgBox "请先确认列名是否重复,如果重复,建表将出现错误!!"
DoEvents
TableName = InputBox("请输入Oracle表名:", "表名输入", "你的表名")
If Not TableName Like "[a-zA-Z一-龢]*" Then MsgBox "表名不是以字母或汉字开头,请从新开始": Exit Sub
riqilie = InputBox("请输入日期的列名(格式为m;n等字母,用符号分开,必须从a→z顺序,可以是aa、ab): (如无日期列请直接点确定,点取消会终止运行代码)", "列名输入", "0")
If riqilie = "" Then MsgBox "您已取消,代码将终止。": Exit Sub
Set regex = CreateObject("VBScript.RegExp")
With regex
.Global = True
.Pattern = "[a-zA-Z]+" ' 匹配一个或多个数字
End With
'因为往Oracle数据库里导入时用到',故先进行替换,以下为替换
DoEvents
Set zhaodao = Range("a1").CurrentRegion.Find("'"): DoEvents
If Not zhaodao Is Nothing Then
Dim answer As VbMsgBoxResult
answer = MsgBox("发现表格中内容存在单引号( ' ),如不替换无法导入数据。是否将其替换为“|||!|||”?", vbYesNo + vbQuestion, "确认替换")
If answer = vbYes Then
' 用户选“是”,执行替换
Range("a1").CurrentRegion.Replace What:="'", Replacement:="|||!|||", LookAt:=xlPart
Else
' 用户选“否”,终止代码运行
MsgBox "操作已取消,代码运行结束。", vbExclamation, "取消"
Exit Sub
End If
End If
answer = MsgBox("请确认是否建表 ??", vbYesNo + vbExclamation, "是否需要建表")
If Not answer = vbYes Then
GoTo bujianbiao
Else
For i = 1 To 100: DoEvents
If Cells(1, i + 1) = "" Then colTypes = colTypes & """" & Cells(1, i) & """" & " varchar2(800)": Exit For
colTypes = colTypes & """" & Cells(1, i) & """" & " varchar2(800)," & vbCrLf
Next i
strText = "aa = " & "'''CREATE TABLE " & TableName & vbCrLf & "(" & colTypes & ")'''" & vbCrLf
strText = strText & "import oracledb" & vbCrLf & "username = ""likeyou32""" & vbCrLf & "dsn = ""192.168.1.139:1521/orclcdb""" _
& vbCrLf & "with oracledb.connect(user=username, password=""wuyou"", dsn=dsn) as connection:" & vbCrLf & _
" with connection.cursor() as cursor:" & vbCrLf & " cursor.execute(aa)" & vbCrLf & _
" connection.commit() " & vbCrLf & " print(""表创建成功!"")"
psCommand = "powershell -Command " & """$bytes = [System.Text.Encoding]::UTF8.GetBytes('" & strText11 & "'); " & _
"$stream = [System.IO.File]::Create('" & filepath4 & "'); " & "$stream.Write($bytes, 0, $bytes.Length); " & "$stream.Close()"""
Set oShell = CreateObject("WScript.Shell")
oShell.Run psCommand, 1, True
Set oShell = Nothing
fileNum = FreeFile
Open filepath4 For Append As #fileNum
Print #fileNum, "# -*- coding: gbk -*-"
Print #fileNum, strText
Close #fileNum
CreateObject("WScript.Shell").Run "cmd /c python " & filepath4, 1, True
MsgBox "已在Oracle数据库中Create表,表名为:" & TableName
End If
'以上为建表
'以下为生成shuju.py
bujianbiao:
riqijia = 0
For i = 1 To 100: DoEvents
If Not regex.Test(riqilie) Then GoTo tiaoguo
If riqijia = regex.Execute(riqilie).Count Then riqijia = regex.Execute(riqilie).Count - 1
riqilie1 = regex.Execute(riqilie)(riqijia)
tiaoguo:
zimu = GetExcelColumnName(i)
'以下重新屡屡逻辑
'注意,一定要把判断日期"UCase(zimu) = UCase(riqilie1)"放到每次条件判断的首次判断
'仅有1列时,生成的元组要带逗号,所以单独拿出来写,仅有1列分为两种情况,1是有日期,2是无日期,因为加上了iserror,所以无日期也不要紧,不对,要紧,因为数字也会变为日期,所以只有要求的列才能设置text日期
If Cells(1, i + 1) = "" And i = 1 And UCase(zimu) = UCase(riqilie1) Then xx = "IF(ISERROR(" & """('""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',),""" & ")," & _
"""('""" & " & " & "CLEAN(" & zimu & 2 & ")" & " & " & """',),""" & "," & """('""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',),"")": GoTo gongshi
If Cells(1, i + 1) = "" And i = 1 Then xx = """('""" & "&" & "CLEAN(" & zimu & 2 & ")" & "&" & """',),""": GoTo gongshi
'以下为有2列及以上时,分日期情况讨论:①当i=1,又分两种情况
If i = 1 Then
If UCase(zimu) = UCase(riqilie1) Then
xx = "IF(ISERROR(" & """('""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',),""" & ")," & _
"""('""" & " & " & "CLEAN(" & zimu & 2 & ")" & " & " & """',""" & "," & """('""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',"")"
riqijia = riqijia + 1
Else
xx = """('""" & "&" & "CLEAN(" & zimu & 2 & ")" & "&" & """',"""
End If
Else
If Cells(1, i + 1) = "" And UCase(zimu) = UCase(riqilie1) Then
xx = xx & "&" & "IF(ISERROR(" & """'""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',),""" & ")," & _
"""'""" & " & " & "CLEAN(" & zimu & 2 & ")" & " & " & """',),""" & "," & """'""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """'),"")"
Exit For
ElseIf Not Cells(1, i + 1) = "" And UCase(zimu) = UCase(riqilie1) Then
xx = xx & "&" & "IF(ISERROR(" & """'""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',),""" & ")," & _
"""'""" & " & " & "CLEAN(" & zimu & 2 & ")" & " & " & """',""" & "," & """'""" & "&" & "TEXT(" & "CLEAN(" & zimu & 2 & "),""yyyy-mm-dd"")" & "&" & """',"")"
riqijia = riqijia + 1
Else
If Cells(1, i + 1) = "" Then
xx = xx & "&" & """'""" & "&" & "CLEAN(" & zimu & 2 & ")" & "&" & """'),""": Exit For
Else
xx = xx & "&" & """'""" & "&" & "CLEAN(" & zimu & 2 & ")" & "&" & """',"""
End If
End If
End If
Next i
gongshi:
Cells(2, i + 1).NumberFormatLocal = "G/通用格式"
Cells(2, i + 1) = "=" & xx
h = Range("a1").CurrentRegion.Rows.Count
If h < 5000000 Then
Cells(2, i + 1).AutoFill Range(Cells(2, i + 1), Cells(h, i + 1))
Else
h = 50
Cells(2, i + 1).AutoFill Range(Cells(2, i + 1), Cells(h, i + 1))
End If
Range(Cells(2, i + 1), Cells(h, i + 1)).Copy
psCommand = "powershell -Command " & """$bytes = [System.Text.Encoding]::UTF8.GetBytes('" & strText11 & "'); " & _
"$stream = [System.IO.File]::Create('" & filepath5 & "'); " & "$stream.Write($bytes, 0, $bytes.Length); " & "$stream.Close()"""
Set oShell = CreateObject("WScript.Shell")
oShell.Run psCommand, 1, True
Set oShell = Nothing
For x1 = 1 To i
If x1 = i Then cc = cc & ":" & x1 & ")'": Exit For
cc = cc & ":" & x1 & ","
Next x1
cc = "'INSERT INTO " & TableName & " VALUES (" & cc
'Set clipboard = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}") ' 创建MSForms.DataObject对象
' clipboard.GetFromClipboard ' 从剪贴板获取文本
' textData = clipboard.GetText
'textData = Left(textData, Len(textData) - 3)
DoEvents
If Not Cells(1, 2) = "" Then
textData = "import win32clipboard" & vbCrLf & "import ast" & vbCrLf & "# 获取剪贴板文本" & vbCrLf & "win32clipboard.OpenClipboard()" & vbCrLf & _
"data = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)" & vbCrLf & "win32clipboard.CloseClipboard()" & vbCrLf & _
"data = '[' + data.rstrip(', \n\r\t') + ']'" & vbCrLf & "cc =" & cc & vbCrLf & "import oracledb" & vbCrLf & "import time" & vbCrLf & _
"import math" & vbCrLf & "def chunked_iterable(data, chunk_size):" & vbCrLf & " for i in range(0, len(data), chunk_size):" & vbCrLf & _
" yield data[i:i + chunk_size]" & vbCrLf & "BATCH_SIZE = 50000" & vbCrLf & "zongshuliang = 0" & vbCrLf & "jici = 0" & vbCrLf & _
"start_time = time.time()" & vbCrLf & "print('正往数据库里导入数据, 请稍等...转列表前')" & vbCrLf & "import json" & vbCrLf & _
"data = data.replace('(', '[').replace(')', ']')" & vbCrLf & "data = data.replace(""'"", '""')" & vbCrLf & "data = data.replace('None', 'null')" & _
vbCrLf & "data = json.loads(data)" & vbCrLf & "# data = [tuple(row) for row in data]" & vbCrLf & "print('正往数据库里导入数据, 请稍等...转后')" & _
vbCrLf & "end_time = time.time()" & vbCrLf & "elapsed = end_time - start_time" & vbCrLf & "print(f'运行时间: {elapsed} 秒')" & vbCrLf & _
"xinbiao =" & "'" & TableName & "'" & vbCrLf & "# data = ast.literal_eval(data)" & vbCrLf & _
"with oracledb.connect(user=""likeyou32"", password=""wuyou"", dsn=""192.168.1.139:1521/orclcdb"") as connection:" & vbCrLf & _
" with connection.cursor() as cursor:" & vbCrLf & " for batch in chunked_iterable(data, BATCH_SIZE):" & vbCrLf & " cursor.executemany(cc,batch)" & vbCrLf & _
" connection.commit()" & vbCrLf & " jici += 1" & vbCrLf & " print(f'已提交 {cursor.rowcount} 行, 用的rowcount,第{jici}次提交 ')" & vbCrLf & _
" zongshuliang += cursor.rowcount" & vbCrLf & _
" print(f""成功向 '{xinbiao}' 表中插入 {zongshuliang} 条记录,倒计时结束,代码自动停止。您老可以去忙别的了....."")" & vbCrLf & _
"for i in range(30, 0, -1):" & vbCrLf & " print(f""倒计时: {i}秒..."",end=""\r"")" & vbCrLf & " time.sleep(1)"
Else
textData = "import win32clipboard" & vbCrLf & "import ast" & vbCrLf & "# 获取剪贴板文本" & vbCrLf & "win32clipboard.OpenClipboard()" & vbCrLf & _
"data = win32clipboard.GetClipboardData(win32clipboard.CF_UNICODETEXT)" & vbCrLf & "win32clipboard.CloseClipboard()" & vbCrLf & _
"data = '[' + data.rstrip(', \n\r\t') + ']'" & vbCrLf & "cc =" & cc & vbCrLf & "import oracledb" & vbCrLf & "import time" & vbCrLf & _
"import math" & vbCrLf & "def chunked_iterable(data, chunk_size):" & vbCrLf & " for i in range(0, len(data), chunk_size):" & vbCrLf & _
" yield data[i:i + chunk_size]" & vbCrLf & "BATCH_SIZE = 50000" & vbCrLf & "zongshuliang = 0" & vbCrLf & "jici = 0" & vbCrLf & _
"start_time = time.time()" & vbCrLf & "print('正往数据库里导入数据, 请稍等...转列表前')" & vbCrLf & "import json" & vbCrLf & _
"data = eval(data)" & vbCrLf & "print('正往数据库里导入数据, 请稍等...转后')" & _
vbCrLf & "end_time = time.time()" & vbCrLf & "elapsed = end_time - start_time" & vbCrLf & "print(f'运行时间: {elapsed} 秒')" & vbCrLf & _
"xinbiao =" & "'" & TableName & "'" & vbCrLf & "# data = ast.literal_eval(data)" & vbCrLf & _
"with oracledb.connect(user=""likeyou32"", password=""wuyou"", dsn=""192.168.1.139:1521/orclcdb"") as connection:" & vbCrLf & _
" with connection.cursor() as cursor:" & vbCrLf & " for batch in chunked_iterable(data, BATCH_SIZE):" & vbCrLf & " cursor.executemany(cc,batch)" & vbCrLf & _
" connection.commit()" & vbCrLf & " jici += 1" & vbCrLf & " print(f'已提交 {cursor.rowcount} 行, 用的rowcount,第{jici}次提交 ')" & vbCrLf & _
" zongshuliang += cursor.rowcount" & vbCrLf & _
" print(f""成功向 '{xinbiao}' 表中插入 {zongshuliang} 条记录,倒计时结束,代码自动停止。您老可以去忙别的了....."")" & vbCrLf & _
"for i in range(30, 0, -1):" & vbCrLf & " print(f""倒计时: {i}秒..."",end=""\r"")" & vbCrLf & " time.sleep(1)"
End If
fileNum = FreeFile
Open filepath5 For Append As #fileNum
Print #fileNum, "# -*- coding: gbk -*-"
Print #fileNum, textData
Close #fileNum
CreateObject("WScript.Shell").Run "cmd /c python " & filepath5, 1, False
End Sub
Function GetExcelColumnName(colNumber As Long) As String
Dim dividend As Long
Dim remainder As Long
Dim columnName As String
dividend = colNumber
columnName = ""
Do While dividend > 0
remainder = (dividend - 1) Mod 26
columnName = Chr(65 + remainder) & columnName ' 65是"A"的ASCII码
dividend = (dividend - remainder - 1) \ 26
Loop
GetExcelColumnName = columnName
End Function
|
|