Check if there is empty Range in vba - vba

I am trying to filter by a list of Condition from the Condition wb to use for the Order wb. I use a checkEmpty range in order to check if there are no matching value then I will clear the filter and start with the next condition. But my code doesn't work and the error is "Range of object_worksheet" failed.
I get the error because even there is no matching value (empty range), the code still jump to Else condition.
Here is my code:
Sub Order()
Dim start As Double
Dim strKeyWord As String
Dim myCount As Integer
Dim checkEmpty As Range
Dim lRow1 As Long
Dim wsOrder As Worksheet
Dim wsCondition As Worksheet
Dim wbOrder As Workbook
Dim wbCondition As Workbook
Dim OrderFile As String
Dim ConditionFile As String
'Open Order wb
OrderFile = Application.GetOpenFilename()
Set wbOrder = Workbooks.Open(OrderFile)
Set wsOrder = wbOrder.Worksheets(1)
'Open Condition wb
ConditionFile = Application.GetOpenFilename()
Set wbCondition = Workbooks.Open(ConditionFile)
Set wsCondition = wbCondition.Worksheets(1)
'using the CountA ws function (all non-blanks)
myCount = Application.CountA(wsCondition.Range("A:A")) - 1
start = 2
For I = 1 To myCount Step 1
strKeyWord = wsCondition.Range("A" & start)
wsOrder.Range("R:R").AutoFilter Field:=1, Criteria1:="=*" & strKeyWord & "*"
'lRow1 = WorksheetFunction.Max(wsOrder.Range("I65536").End(xlUp).Row)
Set checkEmpty = wsOrder.Range("I2:I100").SpecialCells(xlCellTypeVisible)
If checkEmpty Is Nothing Then
On Error Resume Next
wsOrder.ShowAllData
On Error GoTo 0
Else
wsOrder.Range("I2", Range("I" & Rows.Count).End(xlUp)).Copy
With wsCondition
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).PasteSpecial
End With
End If
start = start + 1
Next I
End Sub
Thank you very much!

So the main issue is that you didn't specify a worksheet for Range("I" & Rows.Count).End(xlUp).
Using
wsOrder.Range("I2", Range("I" & wsOrder.Rows.Count).End(xlUp)).Copy
should fix that.
But also I would correct the For I loop because you never use I. But you don't need the start variable and can use I instead which is also auto incremented.
'using the CountA ws function (all non-blanks)
myCount = Application.CountA(wsCondition.Range("A:A")) 'removed the -1
'remove start=2 and replace start with I
For I = 2 To myCount Step 1
strKeyWord = wsCondition.Range("A" & I)
wsOrder.Range("R:R").AutoFilter Field:=1, Criteria1:="=*" & strKeyWord & "*"
'lRow1 = WorksheetFunction.Max(wsOrder.Range("I65536").End(xlUp).Row)
Set checkEmpty = wsOrder.Range("I2:I100").SpecialCells(xlCellTypeVisible)
If checkEmpty Is Nothing Then
On Error Resume Next
wsOrder.ShowAllData
On Error GoTo 0
Else
wsOrder.Range("I2", Range("I" & Rows.Count).End(xlUp)).Copy
With wsCondition
.Cells(.Rows.Count, "B").End(xlUp).Offset(1).PasteSpecial
End With
End If
Next I

Related

How to Get Data from Workbook into User Form Combox and Text Boxes with Excel VBA?

I am trying to get the data from the other Excel workbook into Userform. So when selected from the Dropdown list the user get automatcally fill the textboxes.
Below is the Code I tried but showing error. Please help me to resolve this issue.
Private Sub cmbls_DropButtonClick()
Dim i As Long, LastRow As Long
Dim w As Workbook
Set w = Workbooks.Open("C:\Users\Desktop\Inputs for Gate 1.xlsx")
Set ssheet = w.Worksheets("Sheet1")
'showing error in the below line LastRow'
LastRow = Sheets(“Sheet1”).Range(“A” & Rows.Count).End(xlUp).Row
If Me.cmbls.ListCount = 0 Then
For i = 2 To LastRow
Me.cmbls.AddItem Sheets(“Sheet1”).Cells(i, “A”).Value
Next i
End If
End Sub
Private Sub cmbls_Change()
Dim i As Long, LastRow As Long
Dim w As Workbook
Set w = Workbooks.Open("C:\Users\Inputs for Gate 1.xlsx")
Set ssheet = w.Worksheets("Sheet1")
LastRow = Sheets(“Sheet1”).Range(“A” & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
If Sheets(“Sheet1”).Cells(i, “A”).Value = (Me.cmbls) Or _
Sheets(“Sheet1”).Cells(i, “A”).Value = Val(Me.cmbls) Then
Me.TextBox1 = Sheets(“Sheet1”).Cells(i, “B”).Value
End If
Next
End Sub
The error is due to Smart Quotes wrapping your sheet and range references.
Remove all Smart Quotes with CTRL + F & Find and Replace All swapping (“) & (”) for the correct quote notation, (").
Note the subtle difference betwen the 3 quotes used below. VBA requires the 3rd
“ <> ” <> "
Here are some other updates. You did not declare your worksheet reference and need to qualify all of your objects. This compiles now, but may still produce Run Time Errors or may have Logic Errors present.
Option Explicit
Private Sub cmbls_DropButtonClick()
Dim WB As Workbook: Set WB = Workbooks.Open("C:\Users\Desktop\Inputs for Gate 1.xlsx")
Dim WS As Worksheet: Set WS = WB.Worksheets("Sheet1")
Dim i As Long
If Me.cmbls.ListCount = 0 Then
For i = 2 To WS.Range("A" & WS.Rows.Count).End(xlUp).Row
Me.cmbls.AddItem Sheets("Sheet1").Cells(i, "A").Value
Next i
End If
End Sub
Private Sub cmbls_Change()
Dim WB As Workbook: Set WB = Workbooks.Open("C:\Users\Inputs for Gate 1.xlsx")
Dim WS As Worksheet: Set WS = WB.Worksheets("Sheet1")
Dim i As Long
For i = 2 To WS.Range("A" & WS.Rows.Count).End(xlUp).Row
If WS.Cells(i, "A").Value = (Me.cmbls) Or WS.Cells(i, "A").Value = Val(Me.cmbls) Then
Me.TextBox1 = WS.Cells(i, "B").Value
End If
Next i
End Sub

Excel VBA skips a lot of occurrences

I have a Workbook with 6 Sheets. I am walking through them with For Each. And the task is:
1) Walk though every cell with specified Range
2) If cell is not empty AND contains ONLY number THEN add to the end of the cell " мм". Otherwise SKIP this cell.
But in fact, script does it good only for first sheet (Worksheet). It does no changes to other sheets. I don't know why this happens. I think, that there is some error or mistake in the code, but I double-checked it and everything seems to be correct. Help me please :)
Sub SaveWorksheetsAsCsv()
Dim xWs As Worksheet
Dim xDir As String
Dim folder As FileDialog
Dim r As Range
Dim rr As Range
Dim rrrrrr As Range
Dim cell As Range
k = Cells(Rows.Count, "A").End(xlUp).Row
Set folder = Application.FileDialog(msoFileDialogFolderPicker)
If folder.Show <> -1 Then Exit Sub
xDir = folder.SelectedItems(1)
For Each xWs In Application.ActiveWorkbook.Worksheets
If xWs.Name Like "Worksheet" Then
Set r = Range("FA2:FA" & k)
For Each cell0 In r
If IsEmpty(cell0.Value) = False And IsNumeric(cell0.Value) = True Then
cell0.Value = cell0.Value & " мм"
End If
Next
'xWs.Columns(41).EntireColumn.Delete
End If
If xWs.Name Like "Worksheet 1" Then
Set rr = Range("AG2:AG" & k)
For Each cell1 In rr
If IsEmpty(cell1.Value) = False And IsNumeric(cell1.Value) Then
cell1.Value = cell1.Value & " мм"
End If
Next
'xWs.Columns(126).EntireColumn.Delete
End If
If xWs.Name Like "Worksheet 5" Then
Set rrrrrr = Range("FR2:FR" & k)
For Each cell5 In rrrrrr
If IsEmpty(cell5.Value) = False And IsNumeric(cell5.Value) Then
cell5.Value = cell5.Value & " мм"
End If
Next
End If
xWs.SaveAs xDir & "\" & xWs.Name, xlCSV, local:=True
Next
End Sub
These sets of statements need to be adjusted to correct sheet references. Current code will always look at active sheet and the range reference is not qualified.
Set r = Range("FA2:FA" & k)
Set r = xWs.Range("FA2:FA" & k)
You can shorten-up and utilize your code a lot.
First, your k = Cells(Rows.Count, "A").End(xlUp).Row trying to get the last row, needs to be inside the For Each xWs In Application.ActiveWorkbook.Worksheets , since the last row will be different for each worksheet.
Second, instead of multiple Ifs, you can use Select Case.
Third, there is no need to have 3 different objects for Range, like r, rr, and rrr. The same goes for cell0, cell1 and cell5, you can use just one r and cell.
The only thing different inside your If (my Select Case) is the range you set r. The rest, looping through r.Cells is the same for all 3 criterias, so you can take this part outside the loop, and have it only once.
Modifed Code
Option Explicit
Sub SaveWorksheetsAsCsv()
Dim xWs As Worksheet
Dim xDir As String
Dim folder As FileDialog
Dim r As Range
Dim cell As Range
Dim k As Long
Set folder = Application.FileDialog(msoFileDialogFolderPicker)
If folder.Show <> -1 Then Exit Sub
xDir = folder.SelectedItems(1)
For Each xWs In ThisWorkbook.Worksheets ' it's safer to use ThisWorkbook is you reffer to the worksheets inside the workbook which thid code resides
With xWs
' getting the last row needs to be inside the loop
k = .Cells(.rows.Count, "A").End(xlUp).Row
Set r = Nothing ' reset Range Object
Select Case .Name
Case "Worksheet"
Set r = .Range("FA2:FA" & k)
'xWs.Columns(41).EntireColumn.Delete
Case "Worksheet 1"
Set r = .Range("AG2:AG" & k)
'xWs.Columns(126).EntireColumn.Delete
Case "Worksheet 5"
Set r = .Range("FR2:FR" & k)
End Select
' check if r is not nothing (it passed one of the 3 Cases in the above select case)
If Not r Is Nothing Then
For Each cell In r
If IsEmpty(cell.Value) = False And IsNumeric(cell.Value) Then
cell.Value = cell.Value & " мм"
End If
Next cell
End If
.SaveAs xDir & "\" & .Name, xlCSV, Local:=True
End With
Next xWs
End Sub

Error in copying data fron one workbook to another

I am trying to copy data from one workbook to another.
my source workbook, contains data with 722 rows. but the code is copying only 72 rows.
While I was debugging, in siiurcewkbk, I could see 722 rows being selected but then in destwkb its just 72 rows being pasted.
also, the column in my sourcewb is in AK and I want them to be pasted in column A of destwb.
Could anyone help me to rectify this issue.
Sub Extract()
Dim x As Workbook
Dim y As Workbook
Dim Val As Variant
Dim filename As String
Dim LastCell As Range
Dim LastRow As Long
CopyCol = Split("AK", ",")
LR = Cells(Rows.Count, 1).End(xlUp).Row
LC = Cells(1, Columns.Count).End(xlToLeft).Column
LCell = Activewindow.RangeSelection.SpecialCells(xlCellTypeLastCell).Address
LCC = Activewindow.RangeSelection.SpecialCells(xlCellTypeLastCell).Column
lcr = Activewindow.RangeSelection.SpecialCells(xlCellTypeLastCell).Row
Set y = ThisWorkbook
Dim path1, Path2
path1 = ThisWorkbook.Path
Path2 = path1 & "\Downloads"
Set x = Workbooks.Open(filename:=Path2 & "\Red.xlsx")
For Count = 0 To UBound(CopyCol)
Set temp = Range(CopyCol(Count) & "1:" & CopyCol(Count) & lcr)
If Count = 0 Then
Set CopyRange = temp
Else
Set CopyRange = Union(CopyRange, temp)
End If
Next
CopyRange.Copy
y.Sheets("All").Paste y.Sheets("All").Range("A4")
Application.CutCopyMode = False
x.Close
End Sub
anylead would be helpful.
If you are just coping one column of data from one worksheet to another column in another worksheet there is a lot easier way of doing it.
Does the code below help? Sorry if I've misunderstood your requirements ...
Sub Extract()
Dim Path2 As String '** path to the workbook you want to copy to ***
Dim X As Workbook '*** WorkBook to copy from ****
Dim Y As Workbook '** WorkBook to copy to
Set X = ActiveWorkbook '** This workbook ****
Path2 = "C:\test" '** path of book to copy to
Set Y = Workbooks.Open(filename:=Path2 & "\Red.xlsx")
X.Sheets("From").Range("A:A").Copy Destination:=Y.Sheets("ALL").Range("A1")
Application.CutCopyMode = False
Y.Save
Y.Close
End Sub
Try this, I commented out some lines that were doing nothing as far as I can see because I'm strict about code. Also I added some Dim statements because I always write code with Option Explicit at the top of module, this is there to help the programmer as it traps hidden compile errors.
The solution to your problem is in the lines
Dim rngLastCell As Excel.Range
Set rngLastCell = Range(CopyCol(Count) & "65535").End(xlUp)
so what we're doing here is go to the last line of the sheet on row 65535 (I know later versions have more rows but this number is fine) and then we say End(xlUp) which logically means go up this column until you find some text which will be the bottom row of your block of data.
Just underneath I changed the syntax of the Range statement which is very flexible so one call Range with a string like Range("A1:B3") or one can call Range with two arguments each of them cells, so Range(Range("A1"),Range("B3")).
Option Explicit
Sub Extract()
Dim x As Workbook
Dim y As Workbook
Dim Val As Variant
Dim filename As String
Dim LastCell As Range
Dim LastRow As Long
Dim CopyCol
CopyCol = Split("AK", ",")
'* LR is never used
'LR = Cells(Rows.Count, 1).End(xlUp).Row
'* lc is never used
'lc = Cells(1, Columns.Count).End(xlToLeft).Column
'* LCell is never used
'LCell = ActiveWindow.RangeSelection.SpecialCells(xlCellTypeLastCell).Address
'* LCC is never used
'LCC = ActiveWindow.RangeSelection.SpecialCells(xlCellTypeLastCell).Column
Dim lcr
lcr = ActiveWindow.RangeSelection.SpecialCells(xlCellTypeLastCell).Row
Set y = ThisWorkbook
Dim path1, Path2
path1 = ThisWorkbook.Path
Path2 = path1 & "\Downloads"
Set x = Workbooks.Open(filename:=Path2 & "\Red.xlsx")
Dim Count As Long
For Count = 0 To UBound(CopyCol)
Dim rngLastCell As Excel.Range
Set rngLastCell = Range(CopyCol(Count) & "65535").End(xlUp)
Dim temp As Excel.Range
'Set temp = Range(CopyCol(Count) & "1:" & CopyCol(Count) & lcr)
Set temp = Range(CopyCol(Count) & "1", rngLastCell)
If Count = 0 Then
Dim CopyRange As Excel.Range
Set CopyRange = temp
Else
Set CopyRange = Union(CopyRange, temp)
End If
Next
CopyRange.Copy
y.Sheets("All").Paste y.Sheets("All").Range("A4")
Application.CutCopyMode = False
x.Close
End Sub
CopyCol = Split("AK", ",") is Array("AK")... why?
For Count = 0 To UBound(CopyCol) ... Next runs from 0 to 0 (one cycle).
to put it in an shorter sub, I recommend something like this:
Sub Extract()
Dim path1 As String
path1 = ThisWorkbook.Path & "\Downloads"
Dim CopyCol As String
CopyCol = "AK"
With Workbooks.Open(filename:=path1 & "\Red.xlsx")
With .ActiveSheet
.Range(.Cells(1, CopyCol), .Cells(.Rows.Count, CopyCol).End(xlUp)).Copy ThisWorkbook.Sheets("All").Range("A4")
End With
.Close
End With
End Sub

Formatting a text file and exporting a text file

I have a Range of data in text file like 102201906000-102201911999-23451 around thousands. i want to create a new text file to create the range into numbers like.
102201906000 23451
102201906001 23451
102201906002 23451
till
102201911999 23451
Keeping the last digit as fixed.
I have made following code.
Private Sub CommandButton21_Click()
Application.ScreenUpdating = False
Dim LastRow As Long
LastRow = Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
Dim lCol As Long
Dim rngEnd As String
Dim rng1 As String
Dim rng2 As String
Dim x As Long
Dim Num As Range
For Each Num In Range("A1:A" & LastRow)
lCol = ActiveSheet.UsedRange.Columns.Count
rngEnd = Split(Num, "-")(2)
rng1 = Split(Num, "-")(0) - 1
rng2 = Split(Num, "-")(1)
For x = 1 To rng2 - rng1
Cells(x, lCol + 1) = rng1 + x & " " & rngEnd
Next x
Next Num
Application.ScreenUpdating = True
End Sub
But as i have huge data i am unable to use it properly.
Can i get some help on to create a text file itself when i run a macro without using the spreadsheet.
Waiting for expert advises.
Assuming that you have a text file and want to create another textfile where each line like 102201906000-102201911999-23451 is replaced by a number of lines like 102201906000 23451 it is more natural to use VBScript than straight VBA. You can bypass the need to pull the data into Excel (but -- it is written as an Excel macro so you need to call it from Excel. With minor modification you can remove Excel from the loop completely and use pure VBScript).
To use it you have to include a reference to Microsoft Scripting Runtime to your projects (Tools/References in the VBA editor).
Sub ExpandData(inName As String, outName As String)
Dim FSO As New FileSystemObject
Dim tsIn As TextStream
Dim tsOut As TextStream
Dim startNum, endNum, i, line 'variants
On Error GoTo err_handler
Set tsIn = FSO.OpenTextFile(inName, ForReading)
Set tsOut = FSO.OpenTextFile(outName, ForWriting, True)
Do While tsIn.AtEndOfStream = False
line = Split(tsIn.ReadLine, "-")
If UBound(line) = 2 Then
startNum = CDec(line(0))
endNum = CDec(line(1))
For i = startNum To endNum
tsOut.WriteLine i & " " & line(2)
Next i
End If
Loop
tsIn.Close
tsOut.Close
Exit Sub
err_handler:
Debug.Print "I'm confused!"
End Sub
Used like thus (inName must be different from outName):
Sub test()
ExpandData "C:\Programs\test.txt", "C:\Programs\testout.txt"
End Sub
I would attempt to write then all at once. Looping through and examining them individually should not be necessary if they are sequential.
Private Sub CommandButton21_Click()
Application.ScreenUpdating = False
Dim lr As Long, nmbr As Long, bgn As String, nd As String
With Worksheets("Sheet1") '<~~set this worksheet properly!
lr = .Cells(1, 1).SpecialCells(xlCellTypeLastCell).Row
nd = .Cells(1, 1).Value2
bgn = left(nd, 7)
nmbr = CLng(Mid(nd, 8, 5))
nd = right(nd, 5)
With .Cells(1, Columns.Count).End(xlToLeft).Offset(0, 1).Resize(lr, 1)
.Formula = "=""" & bgn & """&TEXT(ROW(" & Rows(nmbr).Address(0, 0) & "), ""00000_)"")&""" & nd & """"
.Value = .Value2
End With
End With
Application.ScreenUpdating = True
End Sub
This generate sequential number based upon the ROW function. The prefix and suffix are peeled off the first value in A1 only once and used afterwards as string vars.
      

excel macro code is skipping every 2nd line

the below code is to take an employee name, (Column A) andput the range ("A:J") of that row into a new sheet of that employee, if they dont have a sheet, then make one and ad the heading. However, it is skipping every second line, which is causing the line that it is scanning the name on, and the line it is copying from to be different (ie:Employees are going in the wrong sheets, and only 1/2 are getting moved)
Any help would be great
Set rngEmpSales = wsSales.Range("A2", wsSales.Range("A" & Rows.Count).End(xlUp).Address)
Dim wsSales As Worksheet, wsDesSales As Worksheet
Set wsSales = ThisWorkbook.Sheets("Sales")
Dim SalesCount as Range
For Each SalesCount In rngEmpSales
On Error Resume Next
Set wsDesSales = ThisWorkbook.Sheets(Trim(SalesCount.Value))
On Error GoTo 0
If wsDesSales Is Nothing Then
Set wsDesSales = ThisWorkbook.Sheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
wsDesSales.Name = SalesCount.Value
End If
SalesCount(1 - (SalesCount.Row - 1)).Range("A1:J1").Copy wsDesSales.Range("K2")
SalesCount.Range("A" & SalesCount.Row & ":J" & SalesCount.Row).Copy wsDesSales.Range("K" & Rows.Count).End(xlUp).Offset(1, 0)
Set wsDesSales = Nothing
End If
Next SalesCount
Is this what you are trying? (UNTESTED)
Sub Sample()
Dim wsSales As Worksheet, wsDesSales As Worksheet
Dim rngEmpSales As Range, SalesCount As Range
Dim shName As String
Dim lRow As Long, i As Long
Set wsSales = ThisWorkbook.Sheets("Sales")
With wsSales
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set rngEmpSales = .Range("A2:A" & lRow)
For i = 2 To lRow
shName = Trim(.Range("A" & i).Value)
On Error Resume Next
Set wsDesSales = ThisWorkbook.Sheets(shName)
On Error GoTo 0
If wsDesSales Is Nothing Then
Set wsDesSales = ThisWorkbook.Sheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
wsDesSales.Name = shName
End If
.Range("A1:J1").Copy wsDesSales.Range("K2")
.Range("A" & i & ":J" & i).Copy wsDesSales.Range("K" & _
wsDesSales.Rows.Count).End(xlUp).Offset(1, 0)
Set wsDesSales = Nothing
Next i
End With
End Sub
You should use
wssales.Range("A" & SalesCount.Row & ":J" & SalesCount.Row) instead of SalesCount.Range("A" & SalesCount.Row & ":J" & SalesCount.Row)
and
wssales.Range("A1:J1").Copy instead of
SalesCount(1 - (SalesCount.Row - 1)).Range("A1:J1").Copy
The reason is SalesCount itself is a range, when you apply another .Range after it, it will take the relative position.
e.g. Range("A2").Range("A1:J1") becomes Range("A2:J2") and Range("B2").Range("B2:K2") becomes Range("B2:K2")