mike1984
10-09-2015, 01:58 AM
Hi all,
I am using a match formula to look at a database of c. 290k rows of data. As such it is very slow, and I was wondering if there was a way to speed it up using VBA.
I have attached a sample which shows my input data and the output matrix I am trying to calculate.
Can someone suggest a way of perhaps replicating my formulas in VBA as it is taking about 3 hours to calculate the formulas and my company won't stump up the money to buy a more powerful machine! :)
Thanks
Mike
Aflatoon
10-09-2015, 02:37 AM
If you can sort column A ascending, use this in D3:
=IFERROR(IF(VLOOKUP($C3&">"&D$2,$A$3:$A$89,1)=$C3&">"&D$2,"X",""),"")
and fill across and down.
p45cal
10-09-2015, 07:21 AM
I'm wondering whether a pivot table might serve you well.
In the attached I have copied your sheet, but pasted your results matrix as values, just for comparison's sake (and took out the completely blank columns).
Below that I've put in a pivot table based on the data in columns A and B.
Columns A and B were produced from your column A using text-to-columns using the delimiter '>'.
Instead of an 'X' there is a number, being the number of instances of the combination, otherwise the results are exactly the same.
It took me less time to produce the results than it's taken me so far to write this.
Pivot tables are meant to handle the kind of volume of data you have and do it very quickly.
Have I wasted your time?
ps. Do tell others when you cross post where you have done so; http://www.excelforum.com/excel-general/1108142-match-formula-too-slow.html
Why? See http://www.excelguru.ca/content.php?184
(and ExcelForum are quite robust when they discover cross posting without links)
Paul_Hossler
10-09-2015, 07:37 AM
A VBA reformat approach. It does assume that the Output sheet has the right set of Departments
Look at the attachment
Option Explicit
Sub FormatData()
    Dim wsInput As Worksheet, wsTemp As Worksheet, wsOutput As Worksheet
    Dim rInput As Range, rTemp As Range, rOutput As Range, rUnique As Range
    Dim rTempNoHeader As Range
    Dim aNumbers As Variant, aDepts As Variant
    Dim iNumber As Long, iDept As Long, iTemp As Long
    Application.ScreenUpdating = False
    'init input and output
    Set wsInput = ThisWorkbook.Worksheets("Input")
    Set rInput = wsInput.Cells(1, 1).CurrentRegion
    
    Set wsOutput = ThisWorkbook.Worksheets("Output")
    Set rOutput = wsOutput.Cells(1, 1).CurrentRegion
    If rOutput.Rows.Count > 1 Then
        rOutput.Cells(2, 1).Resize(rOutput.Rows.Count - 1, 1).EntireRow.Delete
    End If
    
    'delete any temp ws and copy input
    On Error Resume Next
    Application.DisplayAlerts = False
    ThisWorkbook.Worksheets("Temp").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0
    
    Call wsInput.Copy(, wsInput)
    Set wsTemp = ActiveSheet
    wsTemp.Name = "Temp"
    Set rTemp = wsTemp.Cells(1, 1).CurrentRegion
    Set rTempNoHeader = rTemp.Cells(2, 1).Resize(rTemp.Rows.Count - 1, rTemp.Columns.Count)
    
    'prepare temp, sort, remove dups, split field, create unique list
    rTemp.RemoveDuplicates Columns:=1, Header:=xlYes
    
    With wsTemp.Sort
        .SortFields.Clear
        .SortFields.Add Key:=Range("A1"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
        .SetRange rTempNoHeader
        .Header = xlNo
        .MatchCase = False
        .Orientation = xlTopToBottom
        .SortMethod = xlPinYin
        .Apply
    End With
    
    rTemp.TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
        TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
        Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
        :=">", FieldInfo:=Array(Array(1, 2), Array(2, 2)), TrailingMinusNumbers:=True
    'get unique list
    Call rTemp.Columns(1).Copy(wsTemp.Columns(4))
    wsTemp.Columns(4).RemoveDuplicates Columns:=1, Header:=xlYes
    Set rUnique = wsTemp.Cells(1, 4).CurrentRegion
    Set rUnique = rUnique.Cells(2, 1).Resize(rUnique.Rows.Count, rUnique.Columns.Count)
    wsTemp.Cells(1, 1).Value = "Number"
    wsTemp.Cells(1, 2).Value = "Department"
    wsTemp.Cells(1, 4).Value = "Unique"
    
    'put on output
    Call rUnique.Copy(wsOutput.Cells(2, 1))
    Set rOutput = wsOutput.Cells(1, 1).CurrentRegion
    
    'in to array, transpose to have 1 dim array
    With Application.WorksheetFunction
        aNumbers = .Transpose(rOutput.Columns(1))
        aDepts = .Transpose(.Transpose(rOutput.Rows(1)))
    End With
    
    
    With rTemp
        For iTemp = 2 To .Rows.Count
            iNumber = 0
            iDept = 0
    
            Application.StatusBar = .Cells(iTemp, 1).Value & " -- " & .Cells(iTemp, 2).Value & _
                    Format(iTemp / .Rows.Count, "#0.0%")
            
    
            On Error Resume Next
            iNumber = Application.WorksheetFunction.Match(.Cells(iTemp, 1).Value, aNumbers, 0)
            iDept = Application.WorksheetFunction.Match(.Cells(iTemp, 2).Value, aDepts, 0)
            On Error GoTo 0
            
            If iNumber > 0 And iDept > 0 Then
                rOutput.Cells(iNumber, iDept).Value = "X"
            End If
        Next iTemp
    End With
    
    
    'delete temp
    On Error Resume Next
    Application.DisplayAlerts = False
    ThisWorkbook.Worksheets("Temp").Delete
    Application.DisplayAlerts = True
    On Error GoTo 0
    Application.StatusBar = False
    Application.ScreenUpdating = True
    
    
End Sub
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.