在 Excel COM 中为 Autohotkey 创建数据透视表 table 和图表
Creating Pivot table and chart In Excel COM for Autohotkey
我正在尝试创建一个数据透视图 table,然后是来自 ahk 的数据透视图以嵌入到电子邮件中。我是个菜鸟,所以请原谅我的代码质量。我无法正确设置我的数据透视表 table,并且无法在我的生活中显示图表。我在 post 的底部包含了对我一直在工作的内容以及期望的最终结果的引用。
我的数据是两列,有(可以没有)headers 时间和警告我希望能够创建一个图表来显示随时间变化的警告数量和类型,从要么获取 object 的句柄并将其放入 outlook 电子邮件中,要么只复制粘贴对我有用。请告知如何完成此操作,我想我已经很接近了。
编辑
我更新了下面的代码,得到它(草率我确定)图表被创建,我唯一缺少的是将 "warning" 添加到数据透视表 table 的图例字段,并更改轴(类别)从 "time" 到 "hours" 这将按小时而不是单个时间戳对警告进行分组。如果我手动这样做,我似乎会得到我想要的结果。在那之后,我只想删除图表标题,然后将图表分配给 object 以嵌入,或者将其放入剪贴板。
感谢您的帮助。
f1::Reload
Pause::Pause
f2::ListVars
Pause
!`::
function()
return
function()
{
when:=[]
what:=[]
Nothing:="Nothing to report, have a wonderful day."
TMP:=""
RMRKS:=""
Date1:=""
Date2:=""
EMOUT:=""
EMIN := Clipboard ; Email text var
Loop, Parse, EMIN,`n,`r ; parse email by line
{
tmp := StrSplit(A_LoopField, ";") ; for each line break it into chunks by ";"
rmrks := tmp.6 ; Warn code is in 6th index
If (InStr(rmrks, "Warning")) ; If this is a warning line
{
date1:=StrSplit(tmp.1, "/") ; date/time is in DD/MM/YYYY , split it up by "/"
date2= % date1.2 "/" date1.1 "/" date1.3 ; Rearrange the date into MM/DD/YYYY
EMOUT .= date2 "`t" rmrks "`n" ; Push into VAR "11/24/2016 13:40:45 WARNING MESSAGE"
}
}
EMOUT := StrReplace(EMOUT,"""") ; Replace all of the quotes in the var with Null
Loop, Parse, EMOUT,`n,`r ; Split output by line and then...
{
tmp := StrSplit(A_LoopField, ["`t"]) ; split lines by tab
when.insert(tmp.1) ; insert date/time stamp into "when" array
what.insert(tmp.2) ; insert Warn Code into "what" array
}
if (emout!="") ; If there was stuff to put into array
{
XL := ComObjCreate("Excel.Application") ; create an excel object
wbk := xl.Workbooks.Add ; add a workbook to the object
Xl.Visible := True ; make it visible
XL.Range("A1").Value := "Time" ;Create Time header
XL.Range("A:A").columnwidth := "20"
XL.Range("B:B").columnwidth := "56.86"
XL.Range("B1").Value := "Warning" ; Create Warning Header
for index in when
Xl.Range("A" . index+1).Value := when[index] ;add everything in the "when" array
for index in what
Xl.Range("B" . index+1).Value := what[index] ;add everything in the "what" array
rng := xl.Sheets(1).UsedRange.address
trgt := xl.Sheets(1).range("c1")
pvt := xl.ActiveWorkbook.PivotCaches.Create(xlDatabase:=1, rng, xlPivotTableVersion12:=3).CreatePivotTable(trgt, "PivotTable1", ,xlPivotTableVersion12:=3)
pvt.PivotFields("warning").Orientation := 1
pvt.PivotFields("warning").Position := 1
pvt.PivotFields("time").Orientation := 1
pvt.PivotFields("time").Position := 2
pvt.AddDataField(pvt.PivotFields("Warning"), "Count of Warning", -4112)
Sheet := xl.Sheets(1)
Sheet.Shapes.AddChart.Select
wbk.ShowPivotChartActiveFields := false
xl.ActiveChart.ChartType := 51
xl.ActiveChart.PivotLayout.PivotTable.PivotFields("Warning").Orientation = xlColumnField
xl.ActiveChart.PivotLayout.PivotTable.PivotFields("Warning").Position = 1
return
}
if (emout="")
Msgbox, %Nothing%
Reload
}
来源论坛post我工作的地方是
autohotkey 点com/board/topic/149544-table-pivot-vs-table-pivot-chart-com
和
autohotkey 点com/board/topic/125719-com-excel-pivot-table
我希望嵌入到 Outlook 电子邮件中的最终结果:
示例输入:
两个可能的建议:
- 作为 VBA 功能搜索您想要执行的操作(如果寻求 VBA 建议,更有可能获得良好的搜索结果)
- 在 Excel 中记录一个宏来执行您想执行的操作,然后查看生成的 VBA 代码。换句话说,制作图表并在录制宏时删除标题,然后看看它是否给您带来任何好的代码。在某些情况下这会起作用,在某些情况下它不会。
使用这两种方法中的任何一种都有望让您确定需要将哪些代码或函数转换为脚本。
f1::Reload
Pause::Pause
f2::ListVars
Pause
!`::
SetKeyDelay, -1
Recipients:="test64413@gmail.com"
TMP:=""
RMRKS:=""
Date1:=""
Date2:=""
City:=""
Chart:=""
Warnings:=""
EMAIL:=clipboard
city:=Getcity(EMAIL) ; Get city name
Warnings := ParseWarnings(Email)
if Warnings.MinIndex() ; If there was stuff to put into array
{
Chart := CreateChart(Warnings)
CreateEmail(Chart, city,Warnings)
}
else
msgbox , No Warnings
;###################################################################################################################################################################################################################;
;########################################################################################## Functions ####################################################################################################;
;###################################################################################################################################################################################################################;
ParseWarnings(Email)
{
Warnings := []
EMAIL := StrReplace(EMAIL, """") ; Email text var. Remove all quotes.
Loop, Parse, EMAIL, `n, `r ; Parse email by line
{
tmp := StrSplit(A_LoopField, ";") ; For each line break it into chunks by ";"
rmrks := tmp.6 ; Warn code is in 6th index
If InStr(rmrks, "Warning") ; If this is a warning line
{
date1:=StrSplit(tmp.1, "/") ; Date/time is in DD/MM/YYYY , split it up by "/"
Warnings.Push( {"When": date1.2 "/" date1.1 "/" date1.3, "What": rmrks} ) ;Warnings[1].when //// Warnings[1].what
}
}
return Warnings
}
CreateChart(Warnings)
{
static xlColumnClustered := 51
, xlColumnField := 2
, xlCount := -4112
, xlDatabase := 1
, xlHidden := 0
, xlPivotTableVersion12 := 3
, xlRowField := 1
XL := ComObjCreate("Excel.Application") ; Create an excel object
Wbk := XL.Workbooks.Add ; Add a workbook to the object
Xl.Visible := True ; Make it visible
Sheet := xl.Sheets(1) ; Save a reference to this sheet
; Set Column headings and width
Sheet.Range("A1").Value := "Time" ; Create Time header
Sheet.Range("A:A").columnwidth := "20"
Sheet.Range("B1").Value := "Warning" ; Create Warning Header
Sheet.Range("B:B").columnwidth := "56.86"
; Create a safe array and copy data into it. Then put the safe array into a range.
nRows := Warnings.MaxIndex() ; The number of rows
SafeArray := ComObjArray(12, nRows, 2) ; Create a safearray of the correct size. (Type = 12, Rows = nRows, Columns = 2)
for i, Warning in Warnings
{
SafeArray[i - 1, 0] := Warning.When ; SafeArray[RowNumber, ColumnNumber] := Value
SafeArray[i - 1, 1] := Warning.What ; SafeArray index starts at 0 (not 1)
}
Cell := Sheet.Range("A2") ; The top left cell of the range
Sheet.Range(Cell, Cell.Offset(nRows - 1, 1)).Value := SafeArray ; Put the SafeArray into the Range
rng := Sheet.UsedRange.address
trgt := Sheet.range("c1")
pvt := xl.ActiveWorkbook.PivotCaches
.Create(xlDatabase, rng, xlPivotTableVersion12)
.CreatePivotTable(trgt, "PivotTable1",, xlPivotTableVersion12)
pfWarning := pvt.PivotFields("warning")
pfWarning.Orientation := xlColumnField
pfWarning.Position := 1
pvt.AddDataField(pfWarning, "Count of Warning", xlCount)
; **Is it necessary to set 'pfTime.Orientation' multiple times?
pfTime := pvt.PivotFields("time") ; VBA = With ActiveChart.PivotLayout.PivotTable.PivotFields("Time")
pfTime.Orientation := xlHidden ; VBA = ActiveChart.PivotLayout.PivotTable.PivotFields("Time").Orientation = xlHidden
pfTime.Orientation := xlRowField ; VBA = .Orientation = xlRowField
pfTime.Position := 1 ; VBA = .Position = 1
pfTime.AutoGroup ; Must be Office version >= 2016
pvt.PivotFields("Minutes").Orientation := xlHidden ; ???
pfTime.Orientation := xlHidden ; ???
Sheet.Shapes.AddChart
wbk.ShowPivotChartActiveFields := false
Sheet.ChartObjects(1).Activate
Chart := wbk.ActiveChart
Chart.ChartTitle.Delete
Chart.ChartType := xlColumnClustered
Chart.PivotLayout.PivotTable.PivotFields("Warning").Orientation := xlColumnField
Chart.PivotLayout.PivotTable.PivotFields("Warning").Position := 1
return Chart
}
CreateEmail(Chart, city,warnings)
{
; Reference:
; Alternative method: http://www.mrexcel.com/forum/excel-questions/562877-paste-chart-into-email-body.html
static olMailItem := 0
olApp := ComObjCreate("Outlook.Application")
Email := olApp.CreateItem(olMailItem)
Email.Display
Email.To := "test64413@gmail.com"
Email.Subject := "*** Todays Warnings for Your Gain Site in " city " ***"
body:=warndata(warnings)
header:="`n" "`n" "Data:" "`n"
Email.body := header . body
Chart.ChartArea.Copy
wEditor := olApp.ActiveInspector.WordEditor
wEditor.Application.Selection.Paste
}
GetCity(EMAIL)
{
Split := StrSplit(EMAIL, "`n", "`r")
City := Split[Split.Length()-5]
IfNotInString, City, ,
City := Split[Split.Length()-6]
City:=strsplit(city,",")
City:=City.1
Return City
}
warndata(warnings)
{
for i, Warning in Warnings
body .= "`n" Warning.When "`t" Warning.What "`n" ; This is not right
return body
}
我正在尝试创建一个数据透视图 table,然后是来自 ahk 的数据透视图以嵌入到电子邮件中。我是个菜鸟,所以请原谅我的代码质量。我无法正确设置我的数据透视表 table,并且无法在我的生活中显示图表。我在 post 的底部包含了对我一直在工作的内容以及期望的最终结果的引用。
我的数据是两列,有(可以没有)headers 时间和警告我希望能够创建一个图表来显示随时间变化的警告数量和类型,从要么获取 object 的句柄并将其放入 outlook 电子邮件中,要么只复制粘贴对我有用。请告知如何完成此操作,我想我已经很接近了。
编辑 我更新了下面的代码,得到它(草率我确定)图表被创建,我唯一缺少的是将 "warning" 添加到数据透视表 table 的图例字段,并更改轴(类别)从 "time" 到 "hours" 这将按小时而不是单个时间戳对警告进行分组。如果我手动这样做,我似乎会得到我想要的结果。在那之后,我只想删除图表标题,然后将图表分配给 object 以嵌入,或者将其放入剪贴板。
感谢您的帮助。
f1::Reload
Pause::Pause
f2::ListVars
Pause
!`::
function()
return
function()
{
when:=[]
what:=[]
Nothing:="Nothing to report, have a wonderful day."
TMP:=""
RMRKS:=""
Date1:=""
Date2:=""
EMOUT:=""
EMIN := Clipboard ; Email text var
Loop, Parse, EMIN,`n,`r ; parse email by line
{
tmp := StrSplit(A_LoopField, ";") ; for each line break it into chunks by ";"
rmrks := tmp.6 ; Warn code is in 6th index
If (InStr(rmrks, "Warning")) ; If this is a warning line
{
date1:=StrSplit(tmp.1, "/") ; date/time is in DD/MM/YYYY , split it up by "/"
date2= % date1.2 "/" date1.1 "/" date1.3 ; Rearrange the date into MM/DD/YYYY
EMOUT .= date2 "`t" rmrks "`n" ; Push into VAR "11/24/2016 13:40:45 WARNING MESSAGE"
}
}
EMOUT := StrReplace(EMOUT,"""") ; Replace all of the quotes in the var with Null
Loop, Parse, EMOUT,`n,`r ; Split output by line and then...
{
tmp := StrSplit(A_LoopField, ["`t"]) ; split lines by tab
when.insert(tmp.1) ; insert date/time stamp into "when" array
what.insert(tmp.2) ; insert Warn Code into "what" array
}
if (emout!="") ; If there was stuff to put into array
{
XL := ComObjCreate("Excel.Application") ; create an excel object
wbk := xl.Workbooks.Add ; add a workbook to the object
Xl.Visible := True ; make it visible
XL.Range("A1").Value := "Time" ;Create Time header
XL.Range("A:A").columnwidth := "20"
XL.Range("B:B").columnwidth := "56.86"
XL.Range("B1").Value := "Warning" ; Create Warning Header
for index in when
Xl.Range("A" . index+1).Value := when[index] ;add everything in the "when" array
for index in what
Xl.Range("B" . index+1).Value := what[index] ;add everything in the "what" array
rng := xl.Sheets(1).UsedRange.address
trgt := xl.Sheets(1).range("c1")
pvt := xl.ActiveWorkbook.PivotCaches.Create(xlDatabase:=1, rng, xlPivotTableVersion12:=3).CreatePivotTable(trgt, "PivotTable1", ,xlPivotTableVersion12:=3)
pvt.PivotFields("warning").Orientation := 1
pvt.PivotFields("warning").Position := 1
pvt.PivotFields("time").Orientation := 1
pvt.PivotFields("time").Position := 2
pvt.AddDataField(pvt.PivotFields("Warning"), "Count of Warning", -4112)
Sheet := xl.Sheets(1)
Sheet.Shapes.AddChart.Select
wbk.ShowPivotChartActiveFields := false
xl.ActiveChart.ChartType := 51
xl.ActiveChart.PivotLayout.PivotTable.PivotFields("Warning").Orientation = xlColumnField
xl.ActiveChart.PivotLayout.PivotTable.PivotFields("Warning").Position = 1
return
}
if (emout="")
Msgbox, %Nothing%
Reload
}
来源论坛post我工作的地方是
autohotkey 点com/board/topic/149544-table-pivot-vs-table-pivot-chart-com
和
autohotkey 点com/board/topic/125719-com-excel-pivot-table
我希望嵌入到 Outlook 电子邮件中的最终结果:
示例输入:
两个可能的建议:
- 作为 VBA 功能搜索您想要执行的操作(如果寻求 VBA 建议,更有可能获得良好的搜索结果)
- 在 Excel 中记录一个宏来执行您想执行的操作,然后查看生成的 VBA 代码。换句话说,制作图表并在录制宏时删除标题,然后看看它是否给您带来任何好的代码。在某些情况下这会起作用,在某些情况下它不会。
使用这两种方法中的任何一种都有望让您确定需要将哪些代码或函数转换为脚本。
f1::Reload
Pause::Pause
f2::ListVars
Pause
!`::
SetKeyDelay, -1
Recipients:="test64413@gmail.com"
TMP:=""
RMRKS:=""
Date1:=""
Date2:=""
City:=""
Chart:=""
Warnings:=""
EMAIL:=clipboard
city:=Getcity(EMAIL) ; Get city name
Warnings := ParseWarnings(Email)
if Warnings.MinIndex() ; If there was stuff to put into array
{
Chart := CreateChart(Warnings)
CreateEmail(Chart, city,Warnings)
}
else
msgbox , No Warnings
;###################################################################################################################################################################################################################;
;########################################################################################## Functions ####################################################################################################;
;###################################################################################################################################################################################################################;
ParseWarnings(Email)
{
Warnings := []
EMAIL := StrReplace(EMAIL, """") ; Email text var. Remove all quotes.
Loop, Parse, EMAIL, `n, `r ; Parse email by line
{
tmp := StrSplit(A_LoopField, ";") ; For each line break it into chunks by ";"
rmrks := tmp.6 ; Warn code is in 6th index
If InStr(rmrks, "Warning") ; If this is a warning line
{
date1:=StrSplit(tmp.1, "/") ; Date/time is in DD/MM/YYYY , split it up by "/"
Warnings.Push( {"When": date1.2 "/" date1.1 "/" date1.3, "What": rmrks} ) ;Warnings[1].when //// Warnings[1].what
}
}
return Warnings
}
CreateChart(Warnings)
{
static xlColumnClustered := 51
, xlColumnField := 2
, xlCount := -4112
, xlDatabase := 1
, xlHidden := 0
, xlPivotTableVersion12 := 3
, xlRowField := 1
XL := ComObjCreate("Excel.Application") ; Create an excel object
Wbk := XL.Workbooks.Add ; Add a workbook to the object
Xl.Visible := True ; Make it visible
Sheet := xl.Sheets(1) ; Save a reference to this sheet
; Set Column headings and width
Sheet.Range("A1").Value := "Time" ; Create Time header
Sheet.Range("A:A").columnwidth := "20"
Sheet.Range("B1").Value := "Warning" ; Create Warning Header
Sheet.Range("B:B").columnwidth := "56.86"
; Create a safe array and copy data into it. Then put the safe array into a range.
nRows := Warnings.MaxIndex() ; The number of rows
SafeArray := ComObjArray(12, nRows, 2) ; Create a safearray of the correct size. (Type = 12, Rows = nRows, Columns = 2)
for i, Warning in Warnings
{
SafeArray[i - 1, 0] := Warning.When ; SafeArray[RowNumber, ColumnNumber] := Value
SafeArray[i - 1, 1] := Warning.What ; SafeArray index starts at 0 (not 1)
}
Cell := Sheet.Range("A2") ; The top left cell of the range
Sheet.Range(Cell, Cell.Offset(nRows - 1, 1)).Value := SafeArray ; Put the SafeArray into the Range
rng := Sheet.UsedRange.address
trgt := Sheet.range("c1")
pvt := xl.ActiveWorkbook.PivotCaches
.Create(xlDatabase, rng, xlPivotTableVersion12)
.CreatePivotTable(trgt, "PivotTable1",, xlPivotTableVersion12)
pfWarning := pvt.PivotFields("warning")
pfWarning.Orientation := xlColumnField
pfWarning.Position := 1
pvt.AddDataField(pfWarning, "Count of Warning", xlCount)
; **Is it necessary to set 'pfTime.Orientation' multiple times?
pfTime := pvt.PivotFields("time") ; VBA = With ActiveChart.PivotLayout.PivotTable.PivotFields("Time")
pfTime.Orientation := xlHidden ; VBA = ActiveChart.PivotLayout.PivotTable.PivotFields("Time").Orientation = xlHidden
pfTime.Orientation := xlRowField ; VBA = .Orientation = xlRowField
pfTime.Position := 1 ; VBA = .Position = 1
pfTime.AutoGroup ; Must be Office version >= 2016
pvt.PivotFields("Minutes").Orientation := xlHidden ; ???
pfTime.Orientation := xlHidden ; ???
Sheet.Shapes.AddChart
wbk.ShowPivotChartActiveFields := false
Sheet.ChartObjects(1).Activate
Chart := wbk.ActiveChart
Chart.ChartTitle.Delete
Chart.ChartType := xlColumnClustered
Chart.PivotLayout.PivotTable.PivotFields("Warning").Orientation := xlColumnField
Chart.PivotLayout.PivotTable.PivotFields("Warning").Position := 1
return Chart
}
CreateEmail(Chart, city,warnings)
{
; Reference:
; Alternative method: http://www.mrexcel.com/forum/excel-questions/562877-paste-chart-into-email-body.html
static olMailItem := 0
olApp := ComObjCreate("Outlook.Application")
Email := olApp.CreateItem(olMailItem)
Email.Display
Email.To := "test64413@gmail.com"
Email.Subject := "*** Todays Warnings for Your Gain Site in " city " ***"
body:=warndata(warnings)
header:="`n" "`n" "Data:" "`n"
Email.body := header . body
Chart.ChartArea.Copy
wEditor := olApp.ActiveInspector.WordEditor
wEditor.Application.Selection.Paste
}
GetCity(EMAIL)
{
Split := StrSplit(EMAIL, "`n", "`r")
City := Split[Split.Length()-5]
IfNotInString, City, ,
City := Split[Split.Length()-6]
City:=strsplit(city,",")
City:=City.1
Return City
}
warndata(warnings)
{
for i, Warning in Warnings
body .= "`n" Warning.When "`t" Warning.What "`n" ; This is not right
return body
}