2
votes

I am trying to create a pivot table, and then a pivot chart from ahk for embedding into an email. I am a total noob, so please forgive my code quality. I am having trouble getting my pivot table set up right, and cannot get a chart to appear for the life of me. I have included references to what posts I have been working from, as well as desired end result at the bottom of this post.

My data is two columns, with (could make it without) headers of Time, and Warning I want to be able to create a chart that shows the amount, and type of warning over time, from there either get a handle on the object and place it into an outlook email, or even just a copy paste would work for me. Please advise how to get this done, I think I am so close.

Edit I updated the code below, Got it to the point(sloppy im sure) that the chart gets created, the only things im missing is adding "warning" to the legend field in the pivot table, and changing Axis(catagories) from "time" to "hours" this will group the warnings by hours instead of individual time stamp. if I do that manually I seem to get the result I want. After that, I would just want to delete the chart title, and then assign the chart to an object to embed, or get it onto the clipboard.

Thank you for any help.

        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
}

Source forum posts I am working from are

autohotkey dot com/board/topic/149544-table-pivot-vs-table-pivot-chart-com

and

autohotkey dot com/board/topic/125719-com-excel-pivot-table

End result I am looking for to embed into an outlook email:

http://imgur.com/a/6baLe

Sample input:

http://p.ahkscript.org/?p=a0ceb3b1

2

2 Answers

1
votes

Two possible suggestions:

  1. Search for what you're trying to do as a VBA function (much more likely to get good search results looking for VBA advice)
  2. Record a macro doing what you'd like to do in Excel, then look at the VBA code that gets generated. In other words, make a chart and delete the title while a macro is being recorded, then see if it gives you any good code. In some cases this will work, in some cases it won't.

Using either of these methods will hopefully allow you to figure what code or functions you need to translate into your script.

0
votes

https://xkcd.com/979/

    f1::Reload
    Pause::Pause
    f2::ListVars
    Pause


    !`::

    SetKeyDelay, -1 




    Recipients:="[email protected]"

    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: http://stackoverflow.com/questions/25603864/copy-excel-chart-to-outlook-mail-message
        ; 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 := "[email protected]"
        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
        }