VBS for Excel to count and specific word and use it for a loop - excel

I need little help again.
I have an excel file and I have to do some formatting for further processing.
I stuck at one point:
find a word / or string
get back the number how often it is used in the excel
use this number to put it into a loop
I hope this is possible with VBscript, because I cannot use VBA.
This is how the code looks like, but I doesn't work
Dim objExcel
Set Excel = CreateObject("Excel.Application")
Excel.Visible = True
excel.workbooks.open "C:\Users\............."
excel.Rows("1:34").Select
excel.Selection.Delete
excel.Columns("A:A").Select
excel.Selection.Delete
excel.Range("A1").Select
Number = excel.countIf "A:A", "Ent.Date"
for i = 1 to Number
excel.Cells.Find("Ent.Date").Activate
excel.Activecell.Offset(-1,0).Select
excel.Activecell.resize(RowSize +3).EntireRow.Select
excel.Selection.Delete
next
Please help me.
Thanks

You are close. CountIf() is a method of the WorksheetFunction class in your Excel application. So:
Number = Excel.WorksheetFunction.CountIf("A:A", "Ent.Date")
Unrelated. All of this .Active .Select is unnecessary. Humans Select and Activate, but your script doesn't need to.
Instead:
Set Excel = CreateObject("Excel.Application")
Excel.Visible = True
excel.workbooks.open "C:\Users\............."
excel.Rows("1:34").Delete
excel.Columns("A:A").Delete
Number = excel.WorksheetFunction.CountIf(Excel.Range("A:A"), "Ent.Date")
for i = 1 to Number
excel.Cells.Find("Ent.Date").Offset(-1,0).resize(RowSize +3).EntireRow.Delete
next
Also (and this might be more preference) instead of looping with For you could instead us a While loop:
Set Excel = CreateObject("Excel.Application")
Excel.Visible = True
excel.workbooks.open "C:\Users\............."
excel.Rows("1:34").Delete
excel.Columns("A:A").Delete
Do While excel.WorksheetFunction.CountIf(Excel.Range("A:A"), "Ent.Date") >= 1
excel.Cells.Find("Ent.Date").Offset(-1,0).resize(RowSize +3).EntireRow.Delete
Loop
That causes a little extra overhead since it runs that countif on each loop, but it feels more succinct and less potential for error since you seem to be resizing the range returned by Find() to be more rows and then deleting them all... which means you might be picking off rows that also contain your search criteria, which means you are looping too much in your For Loop. But... perhaps your sheet is set up in such a way that this condition doesn't happen.

Related

What about "Application" as default object in Excel VBA?

I have just written this easy macro in Excel VBA for merging a group of selected cells:
Sub Macro_Merge()
Dim Temp As String
Dim S As Variant
Temp = ""
For Each S In Selection
If Temp = "" Then
Temp = CStr(S.Value)
Else:
Temp = Temp + "," + CStr(S.Value)
End If
Next
Selection.Merge
Selection.Value = Temp
Selection.VerticalAlignment = xlTop
End Sub
This works fine, but I always see that annoying dialog box, warning me about loosing data while merging (which is exactly what I'm trying to avoid in my macro).
I can get rid of that dialog box, configuration the Application's DisplayAlerts property:
Application.DisplayAlerts = False
Selection.Merge
Selection.Value = Temp
Application.DisplayAlerts = True
This is working fine.
So, as Application is the default object, I tried to clean up my code, as follows:
DisplayAlerts = False
Selection.Merge
Selection.Value = Temp
DisplayAlerts = True
As you see, I simply omit mentioning the Application object. This is something which is allowed and I've done in the past. (If not in VBA, then Delphi, maybe?)
... but to my surprise, the dialog box appears again (although pressing F1 brings me to the official "Application.DisplayAlerts" documentation).
This leaves me with a simple question:
If a simple DisplayAlerts = ... does not equal Application.DisplayAlerts = ... anymore, what does it mean and how can I use it?
For your information, I'm working with Excel-365.
DisplayAlerts is an undeclared variable.
Certain Application properties and methods can (effectively) have the Application omitted:
ActiveCell, ActiveSheet, ActiveWorkbook, ActiveWindow, Addins, Charts, Selection, etc.
Calculate, Evaluate, Intersect, Run, Union, etc.
(but see this answer why/how this works):
A boolean property such as DisplayAlerts (EnableEvents, ScreenUpdating, etc) doesn't fall into the above category.
A golden rule in order not to fall into such a trap is the usage of Option Explicit while writing macros.
Just to add some information to the answer of #BigBen. If you write something like Workbooks or ActiveSheet in your code, VBA is not looking into the Application-object - it is looking into a (rather well hidden) object named Global.
The global object is exposing some (but not all) properties and methods of the Application-object, so ActiveSheet is referring to Application.ActiveSheet - but not because the Application has a member with this name but because the Global object defines that ActiveSheet means Application.ActiveSheet. In fact even the Application-object is accessed via the Global object.
There is hardly any information about this Global object or its concept. I found a page from Microsoft describing the Global object of MS Word, but the only explanation there is "Contains top-level properties and methods that don't need to be preceded by the Application property.". For Excel, I found this page on O'Reilly.
From time to time you get strange error messages like "Excel VBA Method 'Range' of object'_global' failed" - this is a pointer to the Global object. I would be glad to learn more about the concepts and mechanics of this object, but I am afraid that there are only very few people around that know more (except of course Mathieu Guindon AKA Mr. Rubberduck...). In daily life, we take it for granted that things like ActiveSheet simply works.

VBA - Using Average function in Sheets.Range

I've tried searching a few different threads but wasn't able to get a solution.
My macro is going to transfer data from one sheet to another. I need to use the AVERAGE function to get the average of a range (on the other sheet)
I'm getting a RUN TIME ERROR 438 error and can't figure out why. I tried using Application.WorksheetFunction but this doesn't bear the correct result and works on the MAX function but not the AVERAGE. I saw a few solutions that involve creating a loop and variables, but I assumed a simple solution should be possible.
Code below:
Option Explicit
Sub Step8CopytoLean()
Dim wblean As Workbook
Dim wbmaster As Workbook
Set wblean = Workbooks("SLA Reporting Lean.xlsx")
Set wbmaster = Workbooks("SLA Reporting MasterFile.xlsx")
Workbooks("Lean.xlsx").Activate
Worksheets("Data").Delete
Workbooks("MasterFile.xlsx").Activate
Worksheets("Data").Copy After:=Workbooks("Lean.xlsx").Sheets("Summary")
Workbooks("Lean.xlsx").Sheets("Summary").Activate
wblean.Sheets("Summary").Range("E4").Value = wbmaster.Sheets("Summary").Range("K20")
wblean.Sheets("Summary").Range("F4").Value = wbmaster.Sheets("Summary").Range("M20")
wblean.Sheets("Summary").Range("E5:E6").Value = wbmaster.Sheets("Summary").Average(Range("K9:K11")) 'line with error
wblean.Sheets("Summary").Range("F5").Value = wbmaster.Sheets("Summary").Max(Range("M8:M11")) 'line with error
Modify the below and try:
Application.WorksheetFunction.Average(ThisWorkbook.Worksheets("Sheet1").Range("A1:A10"))
Something like this:
wblean.Sheets("Summary").Range("E5:E6").Value = Application.WorksheetFunction.Average(wbmaster.Worksheets("Summary").Range("K9:K11"))
wblean.Sheets("Summary").Range("F5").Value = Application.WorksheetFunction.Max(wbmaster.Worksheets("Summary").Range("M8:M11"))

Excel VBA Function stops execution before completion without error message

I set out to write a simple function to determine the length of a string in points. Having googled around I decided to avoid the font metrics problem by having excel do the work for me.
Here is the code.
Option Explicit
Function txtWidthPts(MyText As String) As Integer
'A cell on a working worksheet has been named "WidthTest" for easy reference & to ensure data is not overwritten.
'set WidthTest word wrapping off so that strings placed in there aren't wrapped
Application.ScreenUpdating = False
With [WidthTest]
.WrapText = False
.Value = MyText
'autofit WidthTest
.Columns.AutoFit
'get the width of the column
txtWidthPts = .Width
.ClearContents
End With
End Function
I tested the function by placing it in a cell on a working worksheet thus:
=txtWidthPts("Test123")
When I have this working I will be using it in code not as a worksheet function.
My problem is that the function does not throw an error and stops execution on the line:
.Value = MyText
I have placed the code and name into an empty workbook to ensure no interaction with other workbook contents / code.
I have searched extensively and tried various suggestions (DoEvents, Application.Update = False, etc, etc.) to no result.
I have cleared all breakpoints, closed and opened the workbook & restarted. I have tested with options set to Break on All Errors.
No result.
I suspect I am missing something obvious but it has me beat at the moment.
Any and all suggestions will be most welcome.
So, #YowE3K was right on the money. After fixing the error in the original code (Corrected code above) this runs fine from vba. I knew I was missing something obvious.
Curiosity sub-question: the function works as desired and indeed, as #YowE3K observed, it does not modify the Excel environment. However the result returned is dependent on it appearing to have modified the Excel environment. Seriously WTF. Just wanting to understand.
Thanks again YoWE3K.

Range.MergeCells in Matlab

I am trying to perform a cell merge on an Excel file from Matlab. I don't know anything about this, but tried to use some code I found elsewhere online and adapted it a bit:
Excel = actxserver('Excel.Application');
Workbooks = Excel.Workbooks;
Excel.Visible = 0;
Workbook = Excel.Workbooks.Open('C:\Users\path&filename*.xlsx');
for k=1:length(B)-1
rng = [ExcelCol((k-1)*MaxH+2),num2str(1),':',ExcelCol(k*MaxH+2),num2str(1)];
procrng = [rng{:}];
Range = Excel.Range(procrng);
Range.Select;
Range.MergeCells = True;
Range.HorizontalAlignment = xlCenter;
end
ExcelCol is a user-defined function I found online that converts column number to Excel alphabet notation. It works - no doubt about it.
But when I run & step through the code, I get an error at Range.MergeCells = True. I get: "Undefined function or variable True'.
Can you please help?
Use Range.MergeCells = true or Range.MergeCells = 1. True with a capital T is not a Matlab value.
You'll also need to use Range.HorizontalAlignment = -4108 instead of xlCenter because the ActiveX constants are not exposed to Matlab. There's no good way to get them programmatically; you need to build your own constant table, or do some deep digging with introspection.
You can also use .NET instead of ActiveX to script this Excel stuff from Matlab, and it exposes symbolic constants like xlCenter so you can use them (you just have to package-qualify them). But the using Excel automation through the Matlab/.NET interface has some nasty edge-case issues with moving 1-D vectors and having to explicitly cast objects to different interfaces. I can't recommend one over the other at this point.

Using .Find to look in another worksheet

I have aset of account names in one workbook (the active one), and I need to use the .Find function to look for their ocurrences in another workbook/sheet. I don't think I'm getting the right Object handle for the other workbook/sheet, but nothing I try is working.
For Count = 1 to 10
accName = Cells(Count, 1).Value
AccRow(Count) = OBJECTHANDLE.Find(accName).Row
Next Count
Any help?
Never mind, I found the answer with perserverence (it's so rare at the end of the day). Needs to have the Object defined up to .Range, so:
Workbooks("WORKBOOK").Sheets("SHEET").Range("RANGE")
I hate VBA.

Resources