Home > Back-end >  Summarize number of times or how often a machine stays in a mode and goes out of a mode
Summarize number of times or how often a machine stays in a mode and goes out of a mode

Time:03-06

I am trying to summarize the data in different worksheets in a workbook using VBA please.

The attached picture describes the kind of data on each worksheet and summary table gives an example of how i am trying to summarize.

In short, i am trying to summarize how often a machine goes from one mode to the other mode

Please help to come up with a VBA script for this.

Thanks and appreciate all the help.

enter image description here

CodePudding user response:

Count Group Changes

  • Adjust the values in the constants section especially dName, the name of the destination worksheet.
Option Explicit

Sub CountTimes()
     
    ' Source
    Const sNamesList As String = "Machine #1,Machine #2"
    Const sModesList As String = "Read,Learn,Write"
    Const sTitleAddress As String = "A1"
    Const sFirstCellAddress As String = "B5"
    ' Destination
    Const dName As String = "Table"
    Const dFirstCellAddress As String = "A1"
    Const dTitleList As String = "Machine,Mode,Number of times"
    ' Workbook
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
       
    Dim sNames() As String: sNames = Split(sNamesList, ",")
    Dim sModes() As String: sModes = Split(sModesList, ",")
    Dim smCount As Long: smCount = UBound(sModes)   1
    
    Dim drCount As Long: drCount = (UBound(sNames)   1) * smCount   1
    Dim dTitles() As String: dTitles = Split(dTitleList, ",")
    Dim dcCount As Long: dcCount = UBound(dTitles)   1
    
    Dim dData As Variant: ReDim dData(1 To drCount, 1 To dcCount)
    
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    dict.CompareMode = vbTextCompare
    
    Dim c As Long
    For c = 1 To dcCount
        dData(1, c) = dTitles(c - 1)
    Next c
    Dim dr As Long: dr = 1
    
    Dim sws As Worksheet
    Dim sfCell As Range
    Dim sData As Variant
    Dim sTitle As String
    Dim pMode As String ' previous
    Dim nMode As String ' next
    Dim slrow As Long
    Dim sr As Long
    
    For Each sws In wb.Worksheets(sNames)
        Set sfCell = sws.Range(sFirstCellAddress)
        slrow = sws.Cells(sws.Rows.Count, sfCell.Column).End(xlUp).Row
        sData = sfCell.Resize(slrow - sfCell.Row   1).Value
        sTitle = sws.Range(sTitleAddress)
        For sr = 1 To UBound(sData, 1)
            nMode = CStr(sData(sr, 1))
            If StrComp(nMode, pMode, vbTextCompare) <> 0 Then
                dict(nMode) = dict(nMode)   1
                pMode = nMode
            End If
        Next sr
        For c = 1 To smCount
            dr = dr   1
            dData(dr, 1) = sTitle
            pMode = sModes(c - 1)
            dData(dr, 2) = pMode
            If dict.Exists(pMode) Then
                dData(dr, 3) = dict(pMode)
            End If
        Next c
        pMode = ""
        dict.RemoveAll
    Next sws
    
    ' Write and clear below.
    Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
    With dws.Range(dFirstCellAddress).Resize(, dcCount)
        .Resize(dr).Value = dData
        .Resize(dws.Rows.Count - .Row - dr   1).Offset(dr).Clear
        .Font.Bold = True
        .EntireColumn.AutoFit
    End With
    
    MsgBox "Times counted.", vbInformation
     
End Sub

CodePudding user response:

This can also be accomplished using Power Query, available in Windows Excel 2010 and Excel 365 (Windows or Mac)

To use Power Query

  • Data => Get Date => From Other Sources => Blank Query
  • When the PQ Editor opens, navigate to Home => Advanced Editor and paste the code below into the window that opens.
  • Edit the top codelines to include all of your data ranges (either named ranges or tables) and also the line specifying the custom sort order for your modes (adding in any other modes as needed)
  • Read the comments and explore the Applied Steps to understand the algorithm

M Code*

let

//Assumes each Machine is in a separate Named Range or Table
//  and the Names of the machine are the same as the named range or table
// The list could be generated automatically, but that requires more information about your setup.
    listOfMachines={"Machine1","Machine2"},

//Desired order for output of the modes
    modeOrder ={"Read","Learn","Write"},

//read in every machine list
//add the name of the machine to the start of the list
    Source = List.Generate(
        ()=>[machine=listOfMachines{0}, src=Excel.CurrentWorkbook(){[Name = listOfMachines{0}]}[Content], idx=0],
        each [idx] < List.Count(listOfMachines),
        each [machine=listOfMachines{[idx] 1}, src=Excel.CurrentWorkbook(){[Name = listOfMachines{[idx] 1}]}[Content], idx=[idx] 1],
        each Table.FromColumns({{[machine]}} & Table.ToColumns([src]),{"Machine","Time","Mode"})
    ),

//convert the list of tables into a table of tables
//then expand the tables and set the data types
    #"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandTableColumn(#"Converted to Table", "Column1", {"Machine", "Time", "Mode"}, {"Machine", "Time", "Mode"}),
    #"Filled Down" = Table.FillDown(#"Expanded Column1",{"Machine"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Filled Down",{{"Machine", type text}, {"Time", type time}, {"Mode", type text}}),

//Group by Machine and Mode twice and generate counts for each mode,
//note the use of GroupKind.Local
    #"Grouped Rows" = Table.Group(#"Changed Type", {"Machine", "Mode"}, {}
        ,GroupKind.Local),
    #"Grouped Rows1" = Table.Group(#"Grouped Rows", {"Machine", "Mode"}, {{"Count", each Table.RowCount(_), Int64.Type}}),

//Sort so the Modes are in the desired custom order
    #"Mode Sort Order" = Table.AddColumn(#"Grouped Rows1", "Mode Sort Order", each List.PositionOf(modeOrder,[Mode])),
    #"Sorted Rows" = Table.Sort(#"Mode Sort Order",{{"Machine", Order.Ascending}, {"Mode Sort Order", Order.Ascending}}),
    #"Removed Columns" = Table.RemoveColumns(#"Sorted Rows",{"Mode Sort Order"})
in
    #"Removed Columns"

enter image description here

  • Related