AutoHotKey

Excel正则匹配提取、替换、定位工具

2019-06-04  本文已影响1人  sixtyone

;------------------------------------------------

;名字:Excel正则匹配提取、替换、定位工具

;功能:正则匹配提取、替换、定位

;作者:qq576642385 微信15520035235

;时间:2018-8-26

;------------------------------------------------

#SingleInstance force

#NoEnv 

SetWorkingDir %A_ScriptDir%

Process, Priority,, High

SetControlDelay -1

SendMode Input

#IfWinActive,ahk_exe EXCEL.EXE

#q:: ;热键

ExRegExcel :=Excel_Get()

if !IsObject(ExRegExcel)

{

MsgBox,无活动的Excel对象!

return

}

正则匹配替换定位帮助=

(

-------------------------------------------------

Name  :Excel正则匹配、替换、定位工具

QQ    :576642385(1799)

Weixin :15520035235

Time  : 2018-8-26

-------------------------------------------------

帮助相关说明:

1、此工具仅限于Excel中使用

2、匹配提取、替换都是在原数据单元格执行,注意备份

3、不区分大小写需设置:i) 选项

4、需要把源字符串按多行匹配,需设置:m)(*ANYCRLF)

5、匹配或替换的最大次数:-1 表示全部

6、撤销一次:只能尝试是否能撤销1次,最多1次

7、有公式的单元格,将以结果作为匹配的源数据,如:=10+10  结果为20,将以20的实际形式进行匹配

8、所有操作均不涉及单元格格式的改变

9、正则定位中的非模式:abc定位含有abc的单元格,启用非模式表示定位到不含abc的单元格

10、单元格为数值格式时,数字后面会匹配成功1个空格,不知道为何

11、合并单元格仅第一格存在数据,其他为空白单元格,定位时会匹配空白单元格

)

注意说明=

(

--------------数据无价---------------

1. 执行后不能撤销,请保存好原数据;

2. 正则匹配模式:默认只匹配1次;

3. 正则替换模式:默认全部替换;

--------------慎重使用---------------

)

常用正则代码命令=

(

匹配数字

匹配字母

匹配中文

匹配空白单元格

匹配首尾空格

匹配所有空格

首尾插入文字

分段提取内容

)

参考正则代码=

(

1、非空白单元格-1799:.+

2、非负整数-1799:^\d+$

3、正整数-1799:^[1-9]{1}[0-9]*$

4、非正整数:^((-\d+)|(0+))$

5、负整数:^-[0-9]*[1-9][0-9]*$

6、整数:^-?\d+$

7、手机号码:^((\(\d{2,3}\))|(\d{3}\-))?13\d{9}$

8、电话号码:^((\(\d{2,3}\))|(\d{3}\-))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9] \d{6,7}(\-\d{1,4})?$

9、提取《》中的内容-1799:(?<=《).*?(?=》)

10、提取【】中的内容-1799:(?<=【).*?(?=】)

11、提取〖〗中的内容-1799:(?<=〖).*?(?=〗)

12、提取[]中的内容-1799:(?<=\[).*?(?=\])

13、提取指定内容之前的内容-1799:^.*?(?=xxx)

)

ExRegExMode :="匹配模式"     

ExRegExHighMode :=0

ExRegHelp :=0

ExAddEx :=0

WinGet, ExRegExHwnd,ID,A

Gui,Destroy

Gui Add, GroupBox, x5 y5 w125 h78, 模式设置

Gui Add, Radio, x15 y20 w65 h20 gEx切换模式1 +Checked, 正则匹配

Gui Add, Radio, x15 y40 w65 h20 gEx切换模式2, 正则替换

Gui Add, Radio, x15 y60 w65 h20 gEx切换模式3 , 正则定位

Gui Add, Checkbox, x88 y61 w30 h20 cred vExRegExDWF, 非

Gui Add, GroupBox, x5 y85 w125 h275, 常用正则代码

Gui,Font,s9,Microsoft YaHei

Gui Add, ListView, x10 y103 w114 h250 gExRegExList AltSubmit +Grid +NoSortHdr -Multi -Hdr, ListViewtt

Gui,Font

Gui Add, GroupBox, x135 y5 w255 h355, 功能执行

Gui Add, Text, x143 y23 w120 h23 gExAddEx +0x200, 正则表达式:

Gui Add, Edit, x142 y48 w240 cblue r3 vEx正则表达式 -VScroll

Gui Add, Text, x143 y100 w240 h23 vExReTh +0x200, 如需提取子模式值,请输入子模式的序列号:

Gui Add, Edit, x142 y125 w240 cred r3 vEx正则替换内容 -VScroll

Gui,Font,s9,Microsoft YaHei

Gui Add, Text, x143 y175  cred r3, %注意说明% ;注意事项

Gui,Font

Gui Add, Checkbox, x142 y255 w65 h20 vExRegExSetting gExRegExSetting, 高级设置

Gui Add, Text, x157 y275 w140 h20 +0x200, 最大匹配或者替换次数:

Gui Add, Text, x157 y295 w140 h20 +0x200, 匹配模式匹配项连接符:

Gui,Font,s8 Bold

Gui Add, Edit, x284 y277 w65 h17  vExRegExMaxC -VScroll

Gui Add, Edit, x284 y297 w65 h17  vExRegExLinkF -VScroll ;正则匹配多次时,各匹配间的连接符号

Gui,Font

Gui Add, Button, x142 y325 w110 h25 gExRegExRevoke, 撤销一次 ;尝试撤销一次,不能确保成功

Gui Add, Button, x267 y325 w110 h25 vExRegExAc gEx执行, 匹配提取

Gui Add, Text, x0 y360 w400 h2 0x10 ;单线

Gui Add, Text, x5 y362 w40 h15 gExRegHelp +0x200, 状态栏:

Gui Add, Text, x47 y362 w284 h15 cred vExStateBar +0x200,欢迎使用正则匹配! ;状态栏提示

Gui Font, Bold

Gui Add, Text, x340 y362 w120 h15 +0x200 vExCurrentMode gExClearAll cblue, 匹配模式

Gui Font

Gui Add,Edit,x400 y11 w320 h365 vExRegCKZZ

Loop, parse, 常用正则代码命令, `n, `r

LV_Add(,A_LoopField)

Gui +AlwaysOnTop -MinimizeBox -MaximizeBox +ToolWindow

GuiControl,Disabled,ExRegExMaxC

GuiControl,Disabled,ExRegExLinkF

GuiControl,Disabled,ExRegExDWF

Gui Show, w400 h380, Excel正则匹配、替换、定位

Return

ExRegHelp:

if ExRegHelp=0

{

GuiControl,,ExRegCKZZ,%正则匹配替换定位帮助%

WinMove,Excel正则匹配、替换、定位,,,,728

ExRegHelp=1

ExAddEx=0

}

else

{

WinMove,Excel正则匹配、替换、定位,,,,400

ExRegHelp=0

}

return

ExAddEx:

if ExAddEx=0

{

GuiControl,,ExRegCKZZ,%参考正则代码%

WinMove,Excel正则匹配、替换、定位,,,,728

ExAddEx=1

ExRegHelp=0

}

else

{

WinMove,Excel正则匹配、替换、定位,,,,400

ExAddEx=0

}

return

Ex切换模式1:

ExRegExMode :="匹配模式"

GuiControl,Enable,Ex正则替换内容

GuiControl,Enabled,ExRegExSetting

GuiControl,Disabled,ExRegExDWF

if ExRegExHighMode

{

GuiControl,Enabled,ExRegExMaxC

GuiControl,Enabled,ExRegExLinkF

}

GuiControl,,ExReTh,如需提取子模式值,请输入子模式的序列号:

GuiControl,,ExRegExAc,匹配提取

GuiControl,,ExStateBar,欢迎使用正则匹配!

GuiControl,,ExCurrentMode,%ExRegExMode%

return

Ex切换模式2:

ExRegExMode :="替换模式"

GuiControl,Enable,Ex正则替换内容

GuiControl,Enabled,ExRegExSetting

GuiControl,Disabled,ExRegExDWF

if ExRegExHighMode

{

GuiControl,Enabled,ExRegExMaxC

GuiControl,Disabled,ExRegExLinkF

}

GuiControl,,ExReTh,匹配内容替换为:

GuiControl,,ExRegExAc,正则替换

GuiControl,,ExStateBar,欢迎使用正则替换!

GuiControl,,ExCurrentMode,%ExRegExMode%

return

Ex切换模式3:

ExRegExMode :="定位模式"

GuiControl,Enabled,ExRegExDWF

GuiControl,Disable,Ex正则替换内容

GuiControl,Disable,ExRegExSetting

GuiControl,Disabled,ExRegExMaxC

GuiControl,Disabled,ExRegExLinkF

GuiControl,,ExRegExAc,正则定位

GuiControl,,ExStateBar,欢迎使用正则定位!

GuiControl,,ExCurrentMode,%ExRegExMode%

return

匹配数字:

GuiControl,,Ex正则表达式,\d

GuiControl,,ExStateBar,匹配0-9数字但不匹配小数点及正负符号!

GuiControl,,Ex正则替换内容

return

匹配字母:

GuiControl,,Ex正则表达式,[a-zA-Z]

GuiControl,,ExStateBar,匹配所有字母小写及大写!

GuiControl,,Ex正则替换内容

return

匹配中文:

GuiControl,,Ex正则表达式,[\x{4e00}-\x{9fa5}]

GuiControl,,ExStateBar,匹配所有中文!

GuiControl,,Ex正则替换内容

return

匹配空白单元格:

GuiControl,,Ex正则表达式,^$

GuiControl,,ExStateBar,匹配空白单元格!

GuiControl,,Ex正则替换内容

return

匹配首尾空格:

GuiControl,,Ex正则表达式,(^ +)|(%A_Space%+$)

GuiControl,,ExStateBar,匹配首尾单个或多个空格!

GuiControl,,Ex正则替换内容

return

匹配所有空格:

GuiControl,,Ex正则表达式,%A_Space%

GuiControl,,ExStateBar,匹配所有空格!

GuiControl,,Ex正则替换内容

return

首尾插入文字:

GuiControl,,Ex正则表达式,.+

GuiControl,,ExStateBar,请在“$0”前或后输入需要插入的内容。

GuiControl,,Ex正则替换内容,$0

return

分段提取内容:

GuiControl,,Ex正则表达式,^(.{3}).*

GuiControl,,ExStateBar,例取前三个字符:^(.{3}).* 后3个字符:.*(.{3})$

GuiControl,,Ex正则替换内容,$1

return

ExClearAll:

GuiControl,,Ex正则表达式

GuiControl,,Ex正则替换内容

GuiControl,,ExRegExMaxC

GuiControl,,ExStateBar,清空表达式及替换内容,完成!

return

ExRegExSetting: ;高级设置

if !ExRegExHighMode

{

if ExRegExMode=匹配模式

GuiControl,Enabled,ExRegExLinkF

else

GuiControl,Disabled,ExRegExLinkF

GuiControl,Enabled,ExRegExMaxC

ExRegExHighMode :=1

}

else

{

GuiControl,Disabled,ExRegExMaxC

GuiControl,Disabled,ExRegExLinkF

ExRegExHighMode :=0

}

return

ExRegExList:

if A_GuiEvent = Normal  ; 单击

{

    ExRegExRowNumber = 0 

Loop

{

    ExRegExRowNumber := LV_GetNext(ExRegExRowNumber) 

    if not ExRegExRowNumber

        break

    LV_GetText(ExRegExListItem, ExRegExRowNumber)

    if ExRegExListItem

gosub,%ExRegExListItem%

return

}

}

return

;执行功能

Ex执行:

if RegExMatch(ExRegExcel.selection.address,"(?<![A-Z0-9])\$[A-Z0-9]+:\$[A-Z0-9]+")   

{

ExLastCellAddress :=xlFindLastCell(ExRegExcel)

if !ExLastCellAddress

return

ExRegExNewSelection :=ExRegExcel.Intersect(ExRegExcel.selection,ExRegExcel.Range("$A$1:"ExLastCellAddress))

}

else

{

ExRegExNewSelection :=ExRegExcel.Intersect(ExRegExcel.selection,ExRegExcel.selection)

}

EXxrquzj :=ExRegExNewSelection.Count

Gui,Submit,NoHide

;第2步:开始模式判断

;匹配模式

if ExRegExMode=匹配模式 ;如果是匹配模式

{

if (Ex正则表达式="") ;如果正则表达式为空白,将结束

{

Gui +OwnDialogs

MsgBox,正则表达式为空白!

return

}

if !(Ex正则替换内容 ~= "(^$)|(^[1-9]{1}[0-9]*$)") ;输入子模式序列号格式判断,可为正整数或为空白

{

Gui +OwnDialogs

MsgBox,子模式序列号错误!

return

}

if !ExRegExHighMode ;未开启高级模式

ExRegMatchC :=1 ;需匹配次数为1,不再重复匹配

else ;开启了高级模式

{

if ExRegExMaxC ~= "(^[1-9]{1}[0-9]*$)|(-1)" ;输入如果为正整数或为-1

ExRegMatchC :=ExRegExMaxC

else

{

Gui +OwnDialogs

MsgBox,输入最大匹配次数不正确!

return

}

}

Exzsjidj=0

Gui +OwnDialogs

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

Progress, show

gosub,ExRegExCopyData ;开始备份数据,以便可以尝试撤销一次

      For ExRegExCell,ExRegExRn In ExRegExNewSelection

{

Exzsjidj++

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

ExMatchAllValue :=""

ExMatchArray :=RegExMatchAll(ExRegExCell.text, Ex正则表达式,ExRegMatchC,Ex正则替换内容)

if ExMatchArray

{

for xuhk1,valuel in ExMatchArray

ExMatchAllValue .=ExMatchAllValue ? ExRegExLinkF . valuel :  valuel

}

else

ExMatchAllValue :=""

ExRegExCell.Value :=ExMatchAllValue

}

GuiControl,,ExStateBar,匹配提取完成!

Progress, off

    Sleep,50

    WinActivate,ahk_id %ExRegExHwnd% 

      SetTimer,ExRegExToolTip3,-1

      return

}

;替换模式

  If ExRegExMode=替换模式         

    {

if (Ex正则表达式="") ;如果正则表达式为空白,将结束

{

Gui +OwnDialogs

MsgBox,正则表达式为空白!

return

}

if !ExRegExHighMode ;未开启高级模式

ExRegExLimit :=-1

else ;已开启高级模式

{

if ExRegExMaxC ~= "(^[1-9]{1}[0-9]*$)|(-1)" ;输入如果为正整数或为-1

ExRegExLimit :=ExRegExMaxC

else

{

Gui +OwnDialogs

MsgBox,输入次数不正确!

return

}

}

Exzsjidj=0

Gui +OwnDialogs

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

Progress, show

gosub,ExRegExCopyData ;开始备份数据,以便可以尝试撤销一次

      For ExRegExCell,ExRegExRn In ExRegExNewSelection

{

Exzsjidj++

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

        ExRegExCell.Value :=RegExReplace(ExRegExCell.text,Ex正则表达式,Ex正则替换内容,,ExRegExLimit)

}

GuiControl,,ExStateBar,替换完成!

Progress, off

    Sleep,50

    WinActivate,ahk_id %ExRegExHwnd% 

      SetTimer,ExRegExToolTip1,-1

      return

    }

  Else ;定位模式 ,定位模式不需要备份数据

    {

if (Ex正则表达式="") ;如果正则表达式为空白,将结束

{

Gui +OwnDialogs

MsgBox,正则表达式为空白!

return

}

Exzsjidj=0

Gui +OwnDialogs

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

Progress, show

      ExRegExD :=ComObjCreate("Scripting.Dictionary")

      For ExRegExCell,ExRegExRn In ExRegExNewSelection

      {

        If !ExRegExD.exists(ExRegExCell.Address)

ExRegExD.Add(ExRegExCell.Address,ExRegExCell.Text)

else

            continue

      }

      ExRegExAddress :=""

if !ExRegExDWF   ;定位非模式判断

  {

  for ExRegExKey in ExRegExD

  {

Exzsjidj++

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

    If RegExMatch(ExRegExD.item(ExRegExKey),Ex正则表达式)

        ExRegExAddress .=ExRegExAddress? ","ExRegExKey : ExRegExKey

  }

}

  else

{

  for ExRegExKey in ExRegExD

  {

Exzsjidj++

Progress, % Exzsjidj/Exxrquzj*100 ,执行进度 , 勿动选区, 请稍等。。。

    If RegExMatch(ExRegExD.item(ExRegExKey),Ex正则表达式)=0

        ExRegExAddress .=ExRegExAddress? ","ExRegExKey : ExRegExKey

  }

}

  ExRegExAddress :=StrReplace(ExRegExAddress, "$")              ;删除所有地址的$符号

If ExRegExAddress

  {

    if StrLen(ExRegExAddress)<=255       

  {

ExRegExcel.Intersect(ExRegExcel.Range(ExRegExAddress),ExRegExcel.Range(ExRegExAddress)).Select

Progress, off

    ;;ExRegExcel.Range(ExRegExAddress).Select

    Sleep,50

    WinActivate,ahk_id %ExRegExHwnd% 

GuiControl,,ExStateBar,定位完成!

    SetTimer,ExRegExToolTip2,-1   

    return

  }

  else

  {

ExRegExLen :=0

ExRegExNum :=0

    loop

{

if StrLen(ExRegExAddress)>255

{

          ExRegExNum++

          RegExMatch(ExRegExAddress,"O).{2,255}(?=,)",ExRegExAddress%A_Index%)

          ExRegExLen := ExRegExAddress%A_Index%.Len + 2

          ExRegExAddress :=SubStr(ExRegExAddress,ExRegExLen)

          continue

        }

        ExRegExNum++

        RegExMatch(ExRegExAddress,"O).{2,255}",ExRegExAddress%A_Index%)

        break

}

  ExRegExzAdr :=ExRegExcel.Range(ExRegExAddress1.Value)

Loop, % ExRegExNum - 1

{

  ExRegExIndex :=A_Index + 1

  ExRegExzAdr :=ExRegExcel.Union(ExRegExzAdr,ExRegExcel.Range(ExRegExAddress%ExRegExIndex%.Value))

}

ExRegExcel.Intersect(ExRegExzAdr,ExRegExzAdr).Select

Progress, off

;ExRegExzAdr.Select

  Sleep,50

  WinActivate,ahk_id %ExRegExHwnd%

GuiControl,,ExStateBar,定位完成!

  SetTimer,ExRegExToolTip2,-1 

  return 

  }

  }

Progress, off

GuiControl,,ExStateBar,未找到存在条件的单元格!

}

return

GuiEscape:

GuiClose:

ExRegExcel :=""

Excel :=""

ExNavExcel :=""

oexcel :=""

XlieExcel :=""

  Gui,Destroy

return

ExRegExToolTip1:

ToolTip,正则替换完成

Sleep,400

ToolTip

return

ExRegExToolTip2:

ToolTip,正则定位完成

Sleep,400

ToolTip

return

ExRegExToolTip3:

ToolTip,正则匹配提取完成

Sleep,400

ToolTip

return

;备份数据

ExRegExCopyData:

ExCopyDataD :=ComObjCreate("Scripting.Dictionary")

      For ExCopyCell,ExCopyRn In ExRegExNewSelection

      {

        If !ExCopyDataD.exists(ExCopyCell.Address)

ExCopyDataD.Add(ExCopyCell.Address,ExCopyCell.Formula)

else

{

ExCopyDataD :=""

Gui +OwnDialogs

MsgBox,存在重复选区,请重新选择!

return

}

      }

return

;尝试撤销一次,只能一次

ExRegExRevoke:

if !ExCopyDataD

{

GuiControl,,ExStateBar,已经撤销过1次,或无可撤销的数据!

Gui +OwnDialogs

MsgBox,撤销失败!

return

}

Tcas :=ExCopyDataD.Count

Exzsjidj=0

Gui +OwnDialogs

Progress, % Exzsjidj/Tcas*100 ,执行进度 , 勿动选区, 请稍等。。。

Progress, show

for ExRevokeCellAddr in ExCopyDataD

{

Exzsjidj++

ExRegExcel.Range(ExRevokeCellAddr) :=ExCopyDataD.item(ExRevokeCellAddr)

Progress, % Exzsjidj/Tcas*100 ,执行进度 , 勿动选区, 请稍等。。。

}

ExCopyDataD :=""

Progress, Off

Gui +OwnDialogs

GuiControl,,ExStateBar,撤销数据成功!

MsgBox,撤销成功!

return

RegExMatchAll(str, re, max_num:=1, re_num="") {

  arr:=[], pos:=1, r:="",nc:=1

  if max_num <>-1

{

  While (pos:=RegExMatch(str, re, r, pos+StrLen(r))) and (nc<=max_num)

{

    arr.Push( r%re_num% )

nc++

}

  return, arr.MaxIndex() ? arr : ""

}

  While (pos:=RegExMatch(str, re, r, pos+StrLen(r)))

    arr.Push( r%re_num% )

  return, arr.MaxIndex() ? arr : ""

}

xlFindLastCell(objExcel) {         

static xlByRows    := 1

    , xlByColumns := 2

    , xlPrevious  := 2

lastRow := objExcel.ActiveSheet.Cells.Find("*", , , , xlByRows  , xlPrevious).Row

lastCol := objExcel.ActiveSheet.Cells.Find("*", , , , xlByColumns, xlPrevious).Column

    if lastRow

return objExcel.Cells(lastRow,lastCol).Address

    return

}

; Excel_Get by jethrow (modified)

; Forum:    https://autohotkey.com/boards/viewtopic.php?f=6&t=31840

; Github:  https://github.com/ahkon/MS-Office-COM-Basics/blob/master/Examples/Excel/Excel_Get.ahk

Excel_Get(WinTitle:="ahk_class XLMAIN", Excel7#:=1) {

    static h := DllCall("LoadLibrary", "Str", "oleacc", "Ptr")

    WinGetClass, WinClass, %WinTitle%

    if !(WinClass == "XLMAIN")

        return "Window class mismatch."

    ControlGet, hwnd, hwnd,, Excel7%Excel7#%, %WinTitle%

    if (ErrorLevel)

        return "Error accessing the control hWnd."

    VarSetCapacity(IID_IDispatch, 16)

    NumPut(0x46000000000000C0, NumPut(0x0000000000020400, IID_IDispatch, "Int64"), "Int64")

    if DllCall("oleacc\AccessibleObjectFromWindow", "Ptr", hWnd, "UInt", -16, "Ptr", &IID_IDispatch, "Ptr*", pacc) != 0

        return "Error calling AccessibleObjectFromWindow."

    window := ComObject(9, pacc, 1)

    if ComObjType(window) != 9

        return "Error wrapping the window object."

    Loop

        try return window.Application

        catch e

            if SubStr(e.message, 1, 10) = "0x80010001"

                ControlSend, Excel7%Excel7#%, {Esc}, %WinTitle%

            else

                return "Error accessing the application object."

}

;---------Excel正则匹配提取、替换、定位工具------End

上一篇 下一篇

猜你喜欢

热点阅读