Add separate columns into a dictionary - vba

I am trying to add data from a split range (X5:X?,AX5:AX?) into a VBA dictionary. ? Is determined as the last row of data within the sheet. I am new to VBA and trying to force my way through this.
Public Sub Test
'Creates a dictionary object
Dim orderstatus As Object, path As String
Set orderstatus = CreateObject("Scripting.Dictionary")
Dim order, status 'key and object names
order = "Order #": status = "Order Status"
path = ThisWorkbook.path
'Central District--A Head Water Order Summary
Dim app As New Excel.Application, book As Excel.Workbook
app.Visible = False
Set book = app.Workbooks.Add(path & "\CENTRAL DIST\A HEAD - WATER ORDER SUMMARY.xls")
'A Head #1
Dim A1Head As Integer, last As Integer, l as Integer
l = 4
book.Worksheets("A HEAD #1").Activate
last = Range("X" & Rows.Count).End(xlUp).Row
Set lastCol = Range("X5:X" & last, "AX5:AX" & last)
For Each l In lastCol.Cells
orderstatus.Add lastCol.Value
Next
End Sub
Any help is greatly appreciated!

I think something like this is what you're looking for:
Sub tgr()
Dim OrderStatus As Object
Dim i As Long
Dim Key As Variant
Set OrderStatus = CreateObject("Scripting.Dictionary")
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
With Workbooks.Open(ThisWorkbook.Path & "\CENTRAL DIST\A HEAD - WATER ORDER SUMMARY.xls").Sheets("A HEAD #1")
For i = 5 To .Cells(.Rows.Count, "X").End(xlUp).Row
If Not OrderStatus.Exists(.Cells(i, "X").Value) Then OrderStatus(.Cells(i, "X").Value) = .Cells(i, "AX").Value
Next i
.Parent.Close False
End With
'Print dictionary to text file
Close #1
Open ThisWorkbook.Path & "\OrderStatus Output.txt" For Output As #1
Print #1, "Key" & vbTab & "Value"
For Each Key In OrderStatus.Keys
Print #1, Key & vbTab & OrderStatus(Key)
Next Key
Close #1
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub

Change this
orderstatus.Add lastCol.Value
to this
orderstatus.Add l.Value, 1
This assumes you will have no duplicates because you aren't checking for that and will get an error if you do have duplicates.

you're messing up with Range object and Row index
and you'd better abandon the Activate/ActiveXXX pattern and use fully qualified range references
give this code a try
Option Explicit
Public Sub Test()
'Creates a dictionary object
Dim orderstatus As Object
Set orderstatus = CreateObject("Scripting.Dictionary")
'Central District--A Head Water Order Summary
Dim app As New Excel.Application, book As Excel.Workbook
app.Visible = False
Set book = app.Workbooks.Add(ThisWorkbook.path & "\CENTRAL DIST\A HEAD - WATER ORDER SUMMARY.xls")
'A Head #1
Dim dataRng As Range, r As Range
Dim last As Integer
With book.Worksheets("A HEAD #1")
For Each r In .Range("X5", .Cells(.Rows.Count, "X").End(xlUp))
orderstatus(r.value) = r.Offset(, 26).value
Next
End With
End Sub
Moreover if you're running this macro from within an Excel session already, you don't need to get another instance of it nor explicitly reference it:
Option Explicit
Public Sub Test()
'Creates a dictionary object
Dim orderstatus As Object
Set orderstatus = CreateObject("Scripting.Dictionary")
'Central District--A Head Water Order Summary
Dim book As Workbook
Set book = Workbooks.Add(ThisWorkbook.path & "\CENTRAL DIST\A HEAD - WATER ORDER SUMMARY.xls")
'A Head #1
Dim dataRng As Range, r As Range
Dim last As Integer
With book.Worksheets("A HEAD #1")
For Each r In .Range("X5", .Cells(.Rows.Count, "X").End(xlUp))
orderstatus(r.value) = r.Offset(, 26).value
Next
End With
End Sub

Related

Editing the cell value in Specialcells fails?

I have two sheets, one that information about decks played by players, who owns it, what the deck name is, and earlier names. Then another where I have match information of said player, owner and deck name.
My aim is to update match information deck names to newest. I've these two subprocedures. First finds what we need to update, then uses a filtering subprocedure to filter the match list to only have matches containing the player, owner and deck combination visible.
Then it calls the other method, where I try to update the name. It runs nicely, says happily in the debug log that it has beeen renamed from oldname to new name, but when it's finished, the value in the deck name cell remains unchanged.
What am I doing wrong?
EDIT: I tried out your script, Pefington, and amended the split of for i and for each loops. I also used the Variant approach you suggested. Now it runs again, and says it tries to update 'chulane precon to chulane', but that change is not reflected in the excel sheet.
Had to do an rather ugly way of populating the array of Variants with from the array of Strings.
I also added a rownumber to just check in debugger that it indeed goes through the row with chulane precon, and it does, but still fails to actually save the chulane into the cell. Which is the thing I need help with. :)
Sub CleanOldDeckNames()
' DISABLE EXCEL ANIMATIONS
Application.ScreenUpdating = False
Dim player As String
Dim owner As String
Dim concatenatedOldNames As String
Dim oldNamesArray() As Variant
Dim currentName As String
Dim currentOldName As String
Dim temporaryOldNameStringArray() As String
Dim j As Integer
Dim oldName As Variant
Sheets("Decklist").Select
Call dl_search_deck_hidden_reset
For i = 12 To 50
player = ActiveWorkbook.Worksheets("Decklist").range("A" & i).Value
owner = ActiveWorkbook.Worksheets("Decklist").range("B" & i).Value
currentName = ActiveWorkbook.Worksheets("Decklist").range("C" & i).Value
concatenatedOldNames = ActiveWorkbook.Worksheets("Decklist").range("D" & i).Value
If Not (StrComp(concatenatedOldNames, "") = 0) Then
temporaryOldNameStringArray = Split(concatenatedOldNames, ",")
j = 0
For Each oldNameToBeConverted In temporaryOldNameStringArray
ReDim Preserve oldNamesArray(j)
oldNamesArray(j) = CStr(oldNameToBeConverted)
j = j + 1
Next oldNameToBeConverted
For Each oldName In oldNamesArray
currentOldName = Trim(CStr(oldName))
Sheets("Game Logs").Select
ActiveWorkbook.Worksheets("Game Logs").range("E1:G1").Value = Array(player, owner, currentOldName)
Call gl_find_rename_deck
Call RenameInSpecialCells(currentOldName, currentName)
Next oldName
End If
Next
Call gl_find_rename_deck_reset
' ENABLE EXCEL ANIMATIONS
Application.ScreenUpdating = True
End Sub
Sub RenameInSpecialCells(oldName As String, currentName As String)
For Each cell In ActiveWorkbook.Worksheets("Game Logs").AutoFilter.range.SpecialCells(xlCellTypeVisible)
If (StrComp(cell, oldName) = 0) Then
Dim rownumber As Integer
rownumber = cell.row
cell = currentName
Debug.Print ("Renamed " & oldName & " to " & currentName)
End If
Next cell
End Sub
Edit to add after feedback:
Sub RenameInSpecialCells(oldName As String, currentName As String)
dim rng as range, c as range
set rng = ActiveWorkbook.Worksheets("Game Logs").AutoFilter.range.SpecialCells(xlCellTypeVisible) #.range? can't get intellisense to trigger on this one#
For Each c In rng.cells
If (StrComp(c.value, oldName) = 0) Then
c.value = currentName
Debug.Print ("Renamed " & oldName & " to " & currentName)
End If
Next
End Sub
First post here, and new at coding, but I think I see some issues and hopefully can help.
Dim oldNameS As String
Note the s, plural.
You then use:
For Each oldName In oldNamesArray
Now you are calling oldName (singular) as if it was a member of an oldNames collection, but it is not.
You could go with:
For Each oldNames in oldNamesArray
The second problem I think is that you are trying to use a for each loop on a string array. To do that, your array needs to be a variant.
So your array declaration should read:
Dim oldNamesArray() as Variant
Lastly:
Dim name As Variant
I don't see this one getting used, maybe lost in the process?
With those comments the code looks like this:
Sub CleanOldDeckNames()
' DISABLE EXCEL ANIMATIONS
Application.ScreenUpdating = False
Dim player As String
Dim owner As String
Dim oldName As String
Dim oldNamesArray() As Variant
Dim currentName As String
Dim currentOldName As String
Sheets("Decklist").Select
Call dl_search_deck_hidden_reset
For i = 12 To 50
player = ActiveWorkbook.Worksheets("Decklist").range("A" & i).Value
owner = ActiveWorkbook.Worksheets("Decklist").range("B" & i).Value
currentName = ActiveWorkbook.Worksheets("Decklist").range("C" & i).Value
oldName = ActiveWorkbook.Worksheets("Decklist").range("D" & i).Value
oldNamesArray = Split(oldName, ",")
next
For Each oldName In oldNamesArray
currentOldName = Trim(CStr(oldName)) #not sure if CStr required#
Sheets("Game Logs").Select
ActiveWorkbook.Worksheets("Game Logs").range("E1:G1").Value = Array(player, owner, currentOldName)
Call gl_find_rename_deck
Call RenameInSpecialCells(currentOldName, currentName)
Next
Call gl_find_rename_deck_reset
' ENABLE EXCEL ANIMATIONS
Application.ScreenUpdating = True
End Sub
Sub RenameInSpecialCells(oldName As String, currentName As String)
For Each cell In ActiveWorkbook.Worksheets("Game Logs").AutoFilter.range.SpecialCells(xlCellTypeVisible)
If (StrComp(cell, oldName) = 0) Then
cell = currentName
Debug.Print ("Renamed " & oldName & " to " & currentName)
End If
Next cell
End Sub
Apologies if I'm way off the mark.
Edit to add: Your for each in array loop doesn't use i, so you can run the for i loop and for each loop in sequence rather than nesting them. Code amended accordingly.
I finally managed to circumvent the saving. I could not find any reason for why I could not edit the cell via SpecialCells, so I grabbed the row number and column number and edited it directly in the sheet. Turned out that worked.
I also did not need to use Variant as suggested, this simply works.
Sub CleanOldDeckNames()
' DISABLE EXCEL ANIMATIONS
Application.ScreenUpdating = False
Dim player As String
Dim owner As String
Dim oldNames As String
Dim oldNamesArray() As String
Dim currentName As String
Dim currentOldName As String
Dim j As Integer
Sheets("Decklist").Select
Call dl_search_deck_hidden_reset
For i = 12 To 50
player = ActiveWorkbook.Worksheets("Decklist").range("A" & i).Value
owner = ActiveWorkbook.Worksheets("Decklist").range("B" & i).Value
currentName = ActiveWorkbook.Worksheets("Decklist").range("C" & i).Value
oldNames = ActiveWorkbook.Worksheets("Decklist").range("D" & i).Value
oldNamesArray = Split(oldNames, ",")
Dim name As Variant
For Each oldName In oldNamesArray
currentOldName = Trim(oldName)
Sheets("Game Logs").Select
ActiveWorkbook.Worksheets("Game Logs").range("E1:G1").Value = Array(player, owner, currentOldName)
Call gl_find_rename_deck
Call RenameInSpecialCells(currentOldName, currentName)
Next oldName
Next i
Call gl_find_rename_deck_reset
' ENABLE EXCEL ANIMATIONS
Application.ScreenUpdating = True
End Sub
Sub RenameInSpecialCells(oldName As String, currentName As String)
For Each cell In ActiveWorkbook.Worksheets("Game Logs").AutoFilter.range.SpecialCells(xlCellTypeVisible)
If (StrComp(cell, oldName) = 0) Then
Debug.Print ("Attemtping to rename: " & cell)
ActiveWorkbook.Worksheets("Game Logs").Cells(cell.row, cell.Column).Value = "Chulane"
Debug.Print ("New content: " & ActiveWorkbook.Worksheets("Game Logs").Cells(cell.row, cell.Column))
End If
Next cell
End Sub

Run time error: 424 : Object required when I try to reach range and use range data

I am trying to highligh new excel the same way as old excel and data is large .So I saved the data in range and tried to do find, count if functions in range .But it keep showing "object not find error".I really don't get it since I defined the range object well. Here are part of my codes .I tried to debug by "RangSe1(1, 1).Activate" after I defined the RangSe1 object and it give me the 424 error even from here . I am really confused .
Sub Morningsmall()
Dim strfile As String
Dim iLastrow, iColor, iFind, iLastrow1, iLastrow2, iLastrow3, iLastrow4, iRow As Long
Dim RangSe1, RangSo1, RangSe2, RangSo2, RangS As Range
Dim wbLastday, wbToday As Workbook
Dim wsSettle1, wsSettle2, wsSophis1, wsSophis2 As Worksheet
With Application
.ScreenUpdating = False
.EnableEvents = False
.Calculate
.Calculation = xlCalculationManual
.DisplayStatusBar = False
End With
'Open yesterday's file
MsgBox "Open Yesterday's Settlement Report"
strfile = Application.GetOpenFilename
If strfile <> "False" Then Workbooks.Open strfile
Set wbLastday = ActiveWorkbook
Set wsSettle1 = wbLastday.Sheets("SettlementReport")
Set wsSophis1 = wbLastday.Sheets("Sophis")
iLastrow1 = wsSettle1.Cells(wsSettle1.Rows.Count, 1).End(xlUp).Row
iLastrow2 = wsSophis1.Cells(wsSophis1.Rows.Count, 1).End(xlUp).Row
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)
RangSo1 = wsSophis1.Range("A1:AJ" & iLastrow2)
RangSe1(1, 1).Activate
...
...
...
For i = 2 To iLastrow3
iFind = RangSe2(i, 1)
'a = Application.WorksheetFunction.CountIf(Rang, iFind)
If Application.WorksheetFunction.CountIf(wsSettle1, iFind) > 0 Then
'range1.Find("test id", LookIn:=xlValues)
If RangSe1(wsSettle1.Cells.Find(what:=iFind).Row, 6) = RangSe2(i, 6) Then
iColor = RangSe1.Find(what:=iFind).Interior.Color
If iColor <> 16777215 Then
wsSettle2.Rows(i).Interior.Color = iColor
End If
End If
End If
...
...
...
Your lines saying
Dim RangSe1
'...
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)
is equivalent to
Dim RangSe1 As Variant
'...
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1).Value
which will create a Variant array dimensioned as 1 To iLastrow1, 1 To 43. You can't use an Activate method on the (1, 1)th position of an array, because an array is not an object and therefore does not have methods or properties.
You have two major mistakes that are causing your code to not do what you expect:
1) You are not defining your variables correctly because:
Dim RangSe1, RangSo1, RangSe2, RangSo2, RangS As Range
is equivalent to :
Dim RangSe1 As Variant, RangSo1 As Variant, RangSe2 As Variant, RangSo2 As Variant, RangS As Range
You should use:
Dim RangSe1 As Range, RangSo1 As Range, RangSe2 As Range, RangSo2 As Range, RangS As Range
2) You are not using the Set keyword when assigning a reference to your Range objects so, for instance,
RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)
should be
Set RangSe1 = wsSettle1.Range("A1:AQ" & iLastrow1)

How can I extend a chart in Excel by a certain amount of months including named ranges?

I'm trying to extend all charts in a sheet by 12 months to add another year on a monthly line graph. This is what I have so far.
Sub Chart_Extender()
Dim Rng_Extension As Integer
Dim Series_Formula As String
Dim StartPoint As String
Dim EndPoint As String
Dim CommaSplit As Variant
Dim ColonSplit As Variant
Dim grph As ChartObject
Dim ser As Series
'Determine the length of the extension (in cells)
On Error GoTo BadEntry
Rng_Extension = InputBox( _
"How many cells do you want to extend your chart's series?", _
"Chart Extender")
On Error GoTo 0
For Each grph In ActiveSheet.ChartObjects
For Each ser In grph.Chart.SeriesCollection
Series_Formula = ser.Formula
CommaSplit = Split(Series_Formula, ",")
ColonSplit = Split(CommaSplit(2), ":")
StartPoint = ColonSplit(0)
EndPoint = ColonSplit(1)
EndPoint = Range(EndPoint).Offset(0, Rng_Extension).Address
ser.Values = StartPoint & ":" & EndPoint 'Combine Start and End Point & Set Series = To It
If CommaSplit(1) <> "" Then
ColonSplit = Split(CommaSplit(1), ":")
StartPoint = ColonSplit(0)
EndPoint = ColonSplit(1)
EndPoint = Range(EndPoint).Offset(0, Rng_Extension).Address 'Extended Ending Point Range
ser.XValues = StartPoint & ":" & EndPoint 'Combine Start and End Point & Set Series = To It
End If
End If
Next ser
Next grph
MsgBox "Your chart has been Extended by " & Rng_Extension & " positions."
Exit Sub
End Sub
However, since there are named ranges in the graphs as well it seems to get stuck and has an error at EndPoint=ColonSplit(1) saying "Subscript out of range". Is there a way to fix this? Also is there a way to add another loop to have this go through each sheet in the workbook and extend all of them?
After you have validated user input and are sure that you do need to extend the charts, create a workbook and worksheet object:
Dim oWB As Workbook: Set oWB = ThisWorkbook
Dim oWS As Worksheet
Now add the following loop before any of your FOR loops:
For Each oWS In oWB.Worksheets
' Your FOR loops here
Next
This will go through all the sheets in your workbook.
NOTE: Don't forget to add oWS before you reference a Range or Cell

Not able to get the cell value in foreach loop using excel vba

Hi,
I have enclosed the sheet image.
My requirement is:
I want to get all the "G" column values for the organization matching to a specific organization name (Ex:360 evaluations).
I am getting null value after first loop for the G Column
Sub UsageWeekTrend()
Dim customerName As String
Dim sheetName As String
Dim dataFound As Boolean
Dim selectedCell As Range
Dim rowNumber As Integer
Dim weekMinutes As Double
Dim trendsFile As Workbook
Dim trendsSheet As Worksheet
On Error GoTo errorHandling
sheetName = ActiveSheet.Name
customerName = ActiveSheet.Range("A" & (ActiveCell.row)).Value
dataFound = False
For Each selectedCell In ActiveSheet.Range("A1:A1000")
If UCase(selectedCell.Value) = UCase(customerName) Then
weekMinutes = ActiveSheet.Range("G" & selectedCell.row).Value
Debug.Print weekMinutes
Debug.Print "G" & selectedCell.row
If dataFound = False Then
If trendsFile Is Nothing Then
Set trendsFile = Workbooks.Add()
trendsFile.Activate
Set trendsSheet = trendsFile.ActiveSheet
Else
' add a new sheet to the trends workbook
trendsFile.Activate
Set trendsSheet = Sheets.Add
End If
dataFound = True
rowNumber = 1
trendsSheet.Name = Left(customerName, 10) + " " + Format(Date, "MMDD")
trendsSheet.Cells(rowNumber, 1) = "Users"
trendsSheet.Cells(rowNumber, 2) = "Minutes"
rowNumber = rowNumber + 1
End If
' if a sheet has been created, then we have at least one non-zero value so add data
If dataFound = True Then
trendsSheet.Cells(rowNumber, 1) = customerName
trendsSheet.Cells(rowNumber, 2) = weekMinutes
rowNumber = rowNumber + 1
End If
End If
Next selectedCell
' if we have data, create the chart
If dataFound = True Then
' make sure the trends sheet is active for chart insertion
trendsSheet.Activate
Dim chtChart As ChartObject
Dim chartName As String
Dim endRange As String
' define the end of the range for the chart
endRange = "C" & CStr(rowNumber - 1)
' add chart to current sheet
Set chtChart = ActiveSheet.ChartObjects.Add(Left:=200, Top:=200, Width:=900, Height:=400)
chtChart.Activate
ActiveChart.ChartType = xlLineStacked
ActiveChart.SetSourceData Source:=trendsSheet.Range("A2", endRange)
ActiveChart.HasTitle = True
ActiveChart.ChartTitle.Text = customerName
ActiveChart.ApplyLayout (5)
Else
MsgBox ("No usage data found for customer " + customerName)
End If
Exit Sub
errorHandling:
MsgBox (Err.Description)
End Sub
When you run this line:
trendsFile.Activate
You change the Activesheet, so the 2nd time on the loop you again look at the activesheet
weekMinutes = ActiveSheet.Range("G" & selectedCell.row).Value
but the activesheet has changed. I would change those Activesheet calls to a worksheet object that you assign at the top.
This is always a good read for those new to VBA programming: How to avoid using Select in Excel VBA macros
The issue is that you're using ActiveSheet, and the active sheet is being changed in your code.
As soon as trendsFile.Activate is executed, these two references will have new meanings ActiveSheet.Range("A1:A1000") and ActiveSheet.Range("G" & selectedCell.row).Value.
You've created workbook & worksheet variables for your Trends file, and use those, you also need to create a worksheet variable for your "source" worksheet (not sure how you'd refer to it).
Also, I'd be a bit concerned about this section of code:
If trendsFile Is Nothing Then
Set trendsFile = Workbooks.Add()
trendsFile.Activate
Set trendsSheet = trendsFile.ActiveSheet
Else
' add a new sheet to the trends workbook
trendsFile.Activate
Set trendsSheet = Sheets.Add
End If
I believe you'll be adding a new sheet every time through the loop.
Try something like this:
Sub UsageWeekTrend()
Dim customerName As String
Dim sheetName As String
Dim dataFound As Boolean
Dim selectedCell As Range
Dim rowNumber As Integer
Dim weekMinutes As Double
Dim trendsFile As Workbook
Dim trendsSheet As Worksheet
Dim SourceSheet as worksheet 'this is the place where you start, call it what you will
On Error GoTo errorHandling
set SourceSheet = activesheet 'this will now always be THIS sheet, and won't change
sheetName = SourceSheet.Name
customerName = SourceSheet.Range("A" & (ActiveCell.row)).Value
dataFound = False
For Each selectedCell In SourceSheet.Range("A1:A1000")
If UCase(selectedCell.Value) = UCase(customerName) Then
weekMinutes = SourceSheet.Range("G" & selectedCell.row).Value
Debug.Print weekMinutes
Debug.Print "G" & selectedCell.row
If dataFound = False Then
If trendsFile Is Nothing Then
Set trendsFile = Workbooks.Add()
'trendsFile.Activate - never needed
Set trendsSheet = trendsFile.Sheets("Sheet1") 'use the first sheet, since you just created a brand new workbook
Else
' add a new sheet to the trends workbook
'trendsFile.Activate -- you never need this when you're working with an object instead of "Active"
'you'll find that this line will add a new sheet every time you execute the loop
'once you've created your "trendsFile" workbook. you'll need to do some tweaking here
'to prevent you getting one loop worth of data on each sheet
Set trendsSheet = Sheets.Add
End If
dataFound = True
rowNumber = 1
trendsSheet.Name = Left(customerName, 10) + " " + Format(Date, "MMDD")
trendsSheet.Cells(rowNumber, 1) = "Users"
trendsSheet.Cells(rowNumber, 2) = "Minutes"
rowNumber = rowNumber + 1
End If
' if a sheet has been created, then we have at least one non-zero value so add data
If dataFound = True Then
trendsSheet.Cells(rowNumber, 1) = customerName
trendsSheet.Cells(rowNumber, 2) = weekMinutes
rowNumber = rowNumber + 1
End If
End If
Next selectedCell
'The rest of your routine here...
End Sub

Cannot use named range when it is empty

I have a named range lstVendors that refers to: =OFFSET(Data!$W$2,0,0,COUNTA(Data!$W$2:$W$400),1). I want this range to be populated when the workbook opens. I have the following code for this:
Private Sub Workbook_Open()
Application.WindowState = xlMaximized
Dim rslt()
Dim i As Integer
Dim n As Integer
Dim startRng As Range
Dim DropDown1 As DropDown
ThisWorkbook.Sheets("Dashboard").Shapes("TextBox 6").Visible = False
' Range("lstVendors").Offset(0, 0).Value = "Please Select..."
' Set DropDown1 = ThisWorkbook.Sheets("Dashboard").DropDowns("Drop Down 1")
' DropDown1.Value = 1
On Error Resume Next
If Not IsError(Range("lstVendors")) Then
Range("lstVendors").ClearContents
End If
On Error GoTo 0
rslt = Application.Run("SQLite_Query", "path/to/my/sqlite", "SELECT PROGRAM_ID FROM VENDOR;")
Set startRng = Range("lstVendors")
i = 0
For n = 2 To UBound(rslt)
Range("lstVendors").Offset(i, 0).Value = rslt(n)(0)
i = i + 1
Next n
End Sub
It errors on the Set startRng = Range("lstVendors"). I know this is because there's nothing in the range when I'm trying to set it, because if I put one entry into the named range, the set works, however, I need it populated by the sqlite query on each open as the data changes.
Any suggestions much appreciated.
Try this. You have a dynamic range that doesn't evaluate after you clear the contents. To avoid this, there are probably several ways, but easy to simply hardcode the startRange variable so that it always points to Data!$W$2 address, which is (or rather, will become) the first cell in your lstVendors range.
Private Sub Workbook_Open()
Dim rslt()
Dim i As Integer
Dim n As Integer
Dim startRng As Range
Dim DropDown1 As DropDown
Dim rngList As Range
'// Define your startRange -- always will be the first cell in your named range "lstVendors"
' hardcode the address because the dynamic range may not evalaute.
Set startRange = Sheets("Data").Range("W2")
'// Empty th lstVendors range if it exists/filled
On Error Resume Next
Range("lstVendors").Clear
On Error GoTo 0
'// Run your SQL query
rslt = Application.Run("SQLite_Query", "path/to/my/sqlite", "SELECT PROGRAM_ID FROM VENDOR;")
i = 0
'// Print results to the Worksheet, beginning in the startRange cell
For n = 2 To UBound(rslt)
'Increment from the startRange cell
startRange.Offset(i, 0).Value = rslt(n)(0)
i = i + 1
'Verify that "lstVendors" is being populated
Debug.Print Range("lstVendors").Address
Next n
End Sub
Thanks for the suggestions. Here is what I ended up doing in order to get around my problem. It involves adding something I didn't specify would be ok in my original question, so David's answer is great if what I did isn't an option. I first populated the first two cells in my named range with "Please Select..." and "All". In Sub Workbook_Open() we do this:
Private Sub Workbook_Open()
Application.WindowState = xlMaximized
Dim rslt()
Dim i As Integer
Dim n As Integer
Dim startRng As Range
Dim DropDown1 As DropDown
' Disable our not found message
ThisWorkbook.Sheets("Dashboard").Shapes("TextBox 6").Visible = False
' Set our start range to our named range
Set startRng = Range("lstVendors")
' Grab all vendor names
rslt = Application.Run("SQLite_Query", "path/to/my/sqlite", "SELECT PROGRAM_ID FROM VENDOR;")
' Print result. Skip first two rows as constants "Please Select..." and "All" are populated there
i = 2
For n = 2 To UBound(rslt)
startRng.Offset(i, 0).Value = rslt(n)(0)
i = i + 1
Next n
End Sub
Then we will create Sub Workbook_BeforeClose:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
' Disable the save changes dialog. This workbook will be locked up for display only. No need to confuse the user.
Application.DisplayAlerts = False
' Clear everything below the "Please Select..." and "All" cells in the named range
On Error Resume Next
Range("lstVendors").Offset(2, 0).ClearContents
On Error GoTo 0
' Save the changes to the named range
ThisWorkbook.Save
Application.DisplayAlerts = True
End Sub
This information is going to populate a drop down, so having Please Select and All hardcoded into the named range is acceptable for me. If that stipulation doesn't work for someone else looking at this in the future, please use David's suggestion! Thanks again!