CountIf on a range from different workbook - excel

I have been trying to find the root cause of this issue for a long time, but to no avail.
I am trying to count the number of instances a specific text occurs in another workbook (in this case the instance is "42.1" and the workbook name will be contained in Filename1). For some reason, when I execute the countif directly in the sheet, it yields to the correct answer (which should be 2). But whenever I run the code below, it gives me 3.
All the references appear OK since I manually called each value from another workbook and there was no issue. Could you please help ?
Please diregard CounttIfV, it is essentially equivalent to the application function CountIf and I can use both interchangeably.
'manually define the latest S&OP input file
filename = Application.GetOpenFilename
Shapes("DisplayFilename").TextFrame.Characters.Text = filename
'activate the S&OP Workbook
Filename1 = Split(filename, "\")(UBound(Split(filename, "\")))
Workbooks.Open (Filename1)
Workbooks(Filename1).Activate
'define the correct S&OP worksheet regardless of the date
For Each ws_mould In ActiveWorkbook.Worksheets
If ws_mould.Name Like "*Mould*" Then
Worksheets(ws_mould.Name).Activate
active_ws = ws_mould.Name
End If
Next ws_mould
Workbooks(Filename1).Activate
Set CellRange = Workbooks(Filename1).Worksheets(active_ws).Range(Worksheets(active_ws).Cells(27, 45), Worksheets(active_ws).Cells(53, 45))
'NumBlades = Application.WorksheetFunction.CountA(CellRange)
NumBlades = Module3.COUNTIFv(CellRange, "??42.1#*")
Shapes("DisplayFilename").TextFrame.Characters.Text = active_ws

Related

Extract checkbook value from a closed spreadsheet using Excel VBA

I have a fairly larger number of excel workbooks in a folder. Each workbook has one tab - Sheet1. Sheet1 includes three checkboxs: Checkbox 6, Checkbox 7 and Checkbox 8 in addition to some values in cells. I'm using this code:
Link to Code Used
to extract the cell values, but was hoping it would also be possible to determine the value (status checked or not checked) of each of the checkboxes. Is this possible? Note - None of the checkbox are linked to a particular cell.
There is no way to read anything from a closed file. Even the code you are linking to cannot do this. You will always need a program that opens the file, read the data from it, find the information you want and close it again.
For Excel files you usually use Excel, but it could be something else - I know that Python has an library to read & write Excel files (and there are more), but all of them have to open the file. Open means ask the operating system to read the data from disk, maybe set a lock, maybe later write it back, those kind of things.
That said, what you probably want is to access the data (in your case checkbox settings) without the sheet being visible. You can do so by set Application.ScreenUpdating = False, open the file, read the checkbox values, close the file and reset Application.ScreenUpdating = True. The user will not see anything. I strongly assume that the Excel4-Macro does the same, but you will not find many persons around that are able to deal with Excel4-Macros.
Now to be able to read the value of a checkbox, you need to know if you are dealing with ActiveX or Form controls (or both). I wrote a small prove of concept that can deal with both. You pass the name of a workbook, the name (or number) of a sheet and an array with the name of the checkboxes you want to read. Result is an array with the values of the checkboxes. However you need to know that the values of an ActiveX-checkbox is True or False (or Null if you allow TripleState), while for a form-checkbox it is xlOn or xlOff. In the case a sheet doesn't have a checkbox with the specific name, it will return an arbitrary number
Function getCheckBoxValueFromFile(filename As String, sheet As Variant, checkboxNames) As Variant
Const undefinded = -999
Application.ScreenUpdating = False
Dim wb As Workbook
Set wb = Workbooks.Open(filename)
Dim i As Integer, res()
ReDim res(LBound(checkboxNames) To UBound(checkboxNames))
For i = LBound(checkboxNames) To UBound(checkboxNames)
Dim val As Long
val = undefinded
With wb.Sheets(sheet)
On Error Resume Next
' first try ActiveX-CheckBox
val = .OLEObjects(checkboxNames(i)).Object.Value
' if failed, try Form-CheckBox
If val = undefinded Then val = .CheckBoxes(checkboxNames(i)).Value
On Error GoTo 0
res(i) = val
End With
Next i
wb.Close False
getCheckBoxValueFromFile = res
Application.ScreenUpdating = True
End Function
To test the function:
Sub test()
Dim res, i, cbNames
cbNames = Array("CheckBox1", "Check Box 2")
res = getCheckBoxValueFromFile("C:\TEMP\Book1.xlsx", "Sheet1", cbNames)
For i = LBound(res) To UBound(res)
Debug.Print i & ": " & cbNames(i) & " -> " & res(i)
Next i
End Sub

How to define a cell value as a worksheet

I'm currently using a fixed file name in my code however I'd like to replace this fixed name with the value of a particular cell
I've looked extensively across threads to no luck - I'm quite new to coding so I've found similar issues but nothing I'm able to apply to my coding or adapt for exactly my needs
I've tried using
Set wbBook2 = Workbooks(wsSheet1_1.Range("O35").Value)
and a few other similar steps but to no avail
Dim wbBook1 As Workbook
Dim wsSheet1_1 As Worksheet
Dim wsSheet1_2 As Worksheet
Dim wbBook2 As Workbook
Dim wsSheet2_1 As Worksheet
Set wbBook1 = Workbooks("Main File.xlsm")
Set wsSheet1_1 = wbBook1.Worksheets("Example1")
Set wsSheet1_2 = wbBook1.Worksheets("Example2")
Set wbBook2 = Workbooks("Look Up File.xlsm")
Set wsSheet2_1 = wbBook2.Worksheets("Example3")
The above allows me to use 'wbBook2.Activate' to switch to the workbook where the data is located & take the necessary actions however I'd like to be able to change from using "Look Up File.xlsm" to cell O35 on wsSheet1_1.
Currently I'm just ensuring my look-up file has the same name as is noted in the code but this would obviously lead to failure if this is accidentally re-named or a user titled this LookUp File (omitting the space) for example.
Note that 'wbBook2' will already be open when this code is used & the file name can change. The user separately defines the full file path & name (including .xlsm) which is then opened in a separate macro that needs to remain separate
It's safer to loop through Workbooks and look for a match
Private Function set_wb(ByVal toName As String) As Workbook
' Function set_wb(<String>), returns Workbook Object on match.
' - if no match found, return Nothing
' - invokation example: Set wb1 = set_wb("Book1")
Dim wb As Workbook
For each wb in Application.Workbooks
If wb.Name = toName Then
Set set_wb = wb ' wb found
Exit Function
End If
Next wb
Set set_wb = Nothing ' wb not found
End Function
And would be invoked in your case the following way:
Set wbBook2 = set_wb(wsSheet1_1.Range("O35"))

Loop through files in a folder and countif

I have this VBA code to count all values that are not zero in all excel files saved in a folder and print out the result in the worbook containing the macro. the problem I am having is that it opens the same file (the first one) over and over instead of moving to the next file.
Sub RealCount()
Dim file As String
Dim row As Integer
Dim wb As Workbook
row = 2
file = Dir("\\Daglig rapport\KPI Marknadskommunikation\FEB\*.xl??")
Do While file <> ""
Set wb = Workbooks.Open("\\Daglig rapport\KPI Marknadskommunikation\FEB\*.xl??")
Call ZeroCount
file = Dir("\\Daglig rapport\KPI Marknadskommunikation\FEB\*.xl??")
Loop
End Sub
Here's some suggestions to get it working:
Use a path variable to keep the folder location and make the code easier to read
Fix the Workbooks.Open so the parameter should be the actual file path (I'm kind of surprised Excel's Workbook.Open would actually work with wildcards characters like * or ?)
Check that ZeroCount doesn't call any Dir functions. If you do, then Excel may very well reset your ability to call Dir to correctly get the next file in your loop. If you find that this is happening and you must absolutely call Dir inside of this loop, then you could loop through all the Dir values first and store them into an array. Then make another loop that goes through that array which calls ZeroCount (or any code that needs to use Dir within it)
Here's an example of the first two points taken care of:
Sub RealCount()
Dim path as String
Dim file As String
Dim row As Integer
Dim wb As Workbook
path = "\\Daglig rapport\KPI Marknadskommunikation\FEB\"
row = 2
file = Dir(path & "*.xl??")
Do While file <> ""
Set wb = Workbooks.Open(path & file)
Call ZeroCount
row = row + 1 ' I assume you want to increment row each time as well maybe?
file = Dir()
Loop
End Sub
For some more examples of using VBA's Dir - see here: http://www.exceltrick.com/formulas_macros/vba-dir-function/

Run time error '9' VBA

I get the error 'Subscript Out of Range' when I run the following code; debug points me to the last line:
Dim SrcBook As Workbook
Dim TrgBook As Workbook
Dim SrcSheet As Worksheet
Dim TrgSheet As Worksheet
Dim Sheet_Name As String
Workbooks.Open (CalendarFile)
Sheet_Name = MonthName(Month(SrcSheet.Cells(SrcRow, "D").Value), False)
MsgBox ("Sheet_Name Value is: " & Sheet_Name)
Set TrgSheet = Workbooks(CalendarFile).Worksheets(Sheet_Name)
I have repeatedly verified that CalendarFile is a valid file name (I use the full path filename). Sheet_Name is also the valid name of a sheet in that Workbook. I get a similar error if I try to access the worksheets via numeric indexing [ie, Workbooks(CalendarFile).Worksheets(11) vs Workbooks(CalendarFile).Worksheets(November)]. The MsgBox call verifies that I'm feeding the WorkSheets() method the proper sheet name.
Lastly, ScrRow is properly defined - I am able to use this code to manipulate target WorkSheets in the same WorkBook as the macro is called from in toy/testing applications, but for some reason it is failing when I try to manipulate target WorkSheets in other (open) WorkBooks.
Any help would be greatly appreciated! Thank You!
If CalendarFile is a valid filename, that's your issue. The index you need for Workbooks() is the Workbook.Name, not its file path. For example, if CalendarFile was C:\Foo\Bar.xlsx, you need to use Bar.xlsx.
As for the explanation above, it really doesn't matter because you should really just grab a the reference that Workbooks.Open returns and just use that:
Set TrgBook = Workbooks.Open(CalendarFile)
Sheet_Name = MonthName(Month(SrcSheet.Cells(SrcRow, "D").Value), False)
MsgBox ("Sheet_Name Value is: " & Sheet_Name)
Set TrgSheet = TrgBook.Worksheets(Sheet_Name)
Found the solution, at least to this problem:
Workbooks.Open (CalendarFile)
Requires the full-path-name of the file to open, but further references to the file require just the file name - without any of the path attached. That is,
Workbooks(file_name_without_path.xlsx).Worksheets(Sheet_Name)
This is extremely annoying and should be fixed.

VBA data transfer from one workbook to another, data type mismatch error

I'm new to VBA, but learning. I've written most of the following code myself, some of it was inherited. My goal here is to loop through multiple text files (these each contain a unique set of raw data) and copy (or in some other way transfer) that data into an analysis template that I've made which will then be "saved as" with the same filename as the raw data text file. I've been working on this for several days and have done a significant amount of searching to get this far, however, I'm currently stuck with a "Run-time type '13' error - mismatch data type" that I don't understand so I don't know how to get past it. The error is # "Data.Sheets(Sheet1).Range("A1:G180000").Copy. If I comment out the aforementioned line and the one that follows it and use the line above ("Template.Sheets(Sheet1).Range("A1:G180000").Value...") I still get the same error. My code is posted below and any help is very much appreciated. Thanks :)
Sub Shift_Load_Data_Plotter_Template()
'Josh Smith
'12/27/2013
'Shift Load Data Plotter Template
'This macro will bring up the Open dialog box so you can open multiple text files and analyze them using the Shift Load Data Plotter Template
'Brings up the Open window so you can select multiple excel files to import
Dim fn As Variant, f As Integer
Dim FileName As String
'Data is the source workbook and Template is the destination workbook
Dim Data As Workbook
Dim Template As Workbook
fn = Application.GetOpenFilename("Text files,*.txt", _
1, "Select One Or More Files To Open", , True)
If TypeName(fn) = "Boolean" Then Exit Sub
'the line below was modified from from just "workbooks.open "Z:\..." to "Set Template = Workbooks.open..."
'opens the Shift Load Data Analyzer Template workbook and sets the "Template" variable equal to said workbook
Set Template = Workbooks.Open("Z:\General Reference, Tools\Shift Load Data Analyzer Template.xlsx")
For f = 1 To UBound(fn)
'the line below was modified from just "workbooks.open fn(f)" to what it shows now
'sets the "Data" variable equal to the workbook which contains the data from the text file
Set Data = Workbooks.Open(fn(f))
FileName = ActiveWorkbook.Name
'Data.Activate
'Template.Sheets(Sheet1).Range("A1:G180000").Value = Data.Sheets(Sheet1).Range("A1:G180000").Value
Data.Sheets(Sheet1).Range("A1:G180000").Copy
Template.Sheets(Sheet1).Range("A1").PasteSpecial (xlPasteValues)
'the line below used to be "ActiveWorkbook.SaveAs..."
Template.SaveAs FileName:="Z:\" & FileName & ".xlsx"
Data.Close
Next f
End Sub
The line:
Data.Sheets(Sheet1).Range("A1:G180000").Copy
Should probably read as follows:
Data.Sheets("Sheet1").Range("A1:G180000").Copy
You need quotation marks around the sheet name if you're referring to the name (the Sheets() function is looking for the sheet name you see on the tab in Excel, not the Sheet1, Sheet2, Sheet3, etc. you see in the VBA screen). Otherwise you could write it like this:
Data.Sheet1.Range("A1:G180000").Copy
Try changing it to:
Data.Sheets(1).Range("A1:G180000").Copy
Template.Sheets(1).Range("A1").PasteSpecial (xlPasteValues)

Resources