How to create error message if column contains non-numeric field - VBA - excel

I am trying to write a code to produce an error message if the values of the table are non-numeric. I am not getting any error messages but the code isn't accomplishing the task. Any help? Code below:
Sub Refresh()
'
' Warning Code to check if all values are numeric
'-----------------------------------------------------------------------
Dim sh As Worksheet
Dim i As Integer
Dim bisnumberic As Boolean
bIsNumeric = True
For Each sh In ActiveWorkbook.Sheets
Select Case sh.Name
Case "AltA", "AltB", "AltC1", "AltC2"
Dim lRow As Long
lRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 3 To lRow
If Not IsNumeric(Cells(i, 1).Value) Then
bisnumber = False
End If
Next i
End Select
Next sh
If bIsNumeric = False Then
'There are non-numeric values in your range
MsgBox "There are non-numeric values in your range. Go check-
yourself and try again."
Else
'-----------------------------------------------------------------------
' Code to summarize data Sheets("AlternativeSummary").Select
Range("B5").Select
ActiveSheet.PivotTables("PivotTable5").PivotCache.Refresh
MsgBox "Complete"
'All values in your range are numeric
End If
End Sub

lRow = Cells(Rows.Count, 1).End(xlUp).Row should have a clearly defined parent worksheet. Remember that you are cycling through a series of worksheets. Same with If Not IsNumeric(Cells(i, 1).Value) Then.
Sub Refresh()
'
' Warning Code to check if all values are numeric
'-----------------------------------------------------------------------
Dim sh As Worksheet, i As Long, bIsNumeric As Boolean, lRow As Long, errng as range
bIsNumeric = True
For Each sh In ActiveWorkbook.Worksheets
Select Case sh.Name
Case "AltA", "AltB", "AltC1", "AltC2"
lRow = sh.Cells(sh.Rows.Count, 1).End(xlUp).Row
For i = 3 To lRow
If Not IsNumeric(sh.Cells(i, 1).Value) Then
bIsNumeric = False
set errng = sh.Cells(i, 1)
Exit For
End If
Next i
End Select
If Not bIsNumeric Then Exit For
Next sh
If Not bIsNumeric Then
'There are non-numeric values in your range
MsgBox "There are non-numeric values in your range. Go check yourself and try again." _
& chr(10) & errng.address(0, 0, external:=true)
Else
'---------------------------------------------------
' Code to summarize data
With Sheets("AlternativeSummary")
.Activate
.Range("B5").Select
.PivotTables("PivotTable5").PivotCache.Refresh
MsgBox "Complete"
'All values in your range are numeric
end with
End If
End Sub

The problem here is in your if statement:
If Not IsNumeric(Cells(i, 1).Value) Then
bisnumber = False
End If
You are changing the bisnumber variable.
Later on, you actually check the bIsNumeric variable to see if something is or is not a number. You would need to change:
If Not IsNumeric(Cells(i, 1).Value) Then
bisnumber = False
End If
to:
If Not IsNumeric(Cells(i, 1).Value) Then
bIsNumeric = False
End If
Good code writing - and welcome to Stack Overflow.

Option Explicit
Sub Refresh()
'
' Warning Code to check if all values are numeric
'-----------------------------------------------------------------------
Dim sh As Worksheet
Dim i As Integer
Dim bIsNumeric As Boolean
bIsNumeric = True
For Each sh In ActiveWorkbook.Sheets
Dim lRow As Long
lRow = sh.Cells(Rows.Count, 1).End(xlUp).Row
For i = 3 To lRow + 1
If Not IsNumeric(sh.Cells(i, 1).Value) Then
bIsNumeric = False
End If
Next i
Next sh
If bIsNumeric = False Then 'There are non-numeric values in your range
MsgBox "There are non-numeric values in your range. Go check-yourself and try again."
Else
'-----------------------------------------------------------------------
' Code to summarize data Sheets("AlternativeSummary").Select
Range("B5").Select
ActiveSheet.PivotTables("PivotTable5").PivotCache.Refresh
MsgBox "Complete"
'All values in your range are numeric
End If
End Sub
This will loop through all the sheets and check for non-numeric fields.

Related

Looping through a range to find a value

I have a worksheet that has columns 1-8, rows 3 through the last row. I would like to loop through each cell to find out if a value of 1 is present. If it is then that row is copied and inserted for each value of 1, additionally that new row will have a text inserted in cell (13,row) then moved to the next row. This is as far as I got....thanks!
Sub Workcenter()
Application.ScreenUpdating = False
On Error Resume Next
Application.DisplayAlerts = False
On Error GoTo 0
Dim Test As Worksheet
Set TS = Worksheets("Test")
Application.DisplayAlerts = True
For k = 1 To 8
For j = 4 To TS.Cells(Rows.Count, k).End(xlUp).Row
If TS.Cells(j, k).Value = 1 Then TS.Cells.Activate
'TS.Cells.Activate.Row.Select
Rows(ActiveCell.Row).Select
Selection.Copy
Selection.Insert Shift:=xlDown
'ShopOrderNumRow = j
Next j
Next k
End Sub
Will try giving some example knowing that I still don't understand how the inserting is occurring for each cell of a row.
Providing more detail, or example of before/after in your post may help.
As for an example, since you're marking only a single cell in each row, I would suggest Find() for value of 1 to determine if you need to write to that specific cell.
'untested code
sub test()
toggle false
dim rowNum as long
for rowNum = firstRow to lastRow Step 1
with sheets(1)
with .range(.cells(rowNum,1),.cells(rowNum,8))
dim foundCell as range
set foundCell = .find(1)
if not foundCell is nothing then .cells(rowNum,13).value = "text"
end with
end with
next iterator
toggle true
end sub
private sub toggle(val as boolean)
with application
.screenupdating = val
.enableevents = val
end with
end sub
Edit1: Looks like countif() may be the saviour here.
Edit2: Tested code input (untested code part of Edit1)
Sub test()
Dim lastRow As Long: lastRow = 10
Dim firstRow As Long: firstRow = 1
toggle False
Dim rowNum As Long
For rowNum = lastRow To firstRow Step -1
With Sheets(1)
Dim countRange As Range
Set countRange = .Range(.Cells(rowNum, 1), .Cells(rowNum, 8))
Dim countOfOnes As Long
countOfOnes = Application.CountIf(countRange, 1)
If countOfOnes > 0 Then
With .Rows(rowNum)
.Copy
.Offset(1).Resize(countOfOnes).Insert Shift:=xlDown
End With
.Cells(rowNum, 13).Value = "text"
End If
End With
Next rowNum
toggle True
End Sub
Private Sub toggle(val As Boolean)
With Application
.ScreenUpdating = val
.EnableEvents = val
End With
End Sub
Tested using this data:
Output from running code:

Vba: Delete excel sheets not mentioned in the list (the list only contains numeric value)

I need to delete sheets not mentioned in the given list(Range is A7:A350).
I found this vba but the problem is it deletes all the sheets from my workbook, maybe because sheetname is in numeric. I would really appreciate any help.
Sub Deletenotinlist()
Dim i As Long
Dim cnt As Long
Dim xWb, actWs As Worksheet
Set actWs = ThisWorkbook.ActiveSheet
cnt = 0
Application.DisplayAlerts = False
For i = Sheets.Count To 1 Step -1
If Not ThisWorkbook.Sheets(i) Is actWs Then
xWb = Application.Match(Sheets(i).Name, actWs.Range("A7:A350"), 0)
If IsError(xWb) Then
ThisWorkbook.Sheets(i).Delete
cnt = cnt + 1
End If
End If
Next
Application.DisplayAlerts = True
If cnt = 0 Then
MsgBox "Not find the sheets to be seleted", vbInformation, "Kutools for Excel"
Else
MsgBox "Have deleted" & cnt & "worksheets"
End If
End Sub
I think I would do it this way.
Sub DeleteSheets()
Dim sht As Worksheet
Dim rng As Range
Set rng = Sheets("Sheet1").Range("A2:A10")
Application.DisplayAlerts = False
For Each sht In ActiveWorkbook.Worksheets
If Application.CountIf(rng, sht.Name) = 0 Then
sht.Delete
End If
Next sht
Application.DisplayAlerts = True
End Sub
What you try doing can be accomplished in many ways, but I tried adapting your code to place the missing sheets name in an array and select them at the end. If selection is convenient, you can replace Select with Delete:
Sub Deletenotinlist()
Dim i As Long, cnt As Long, xWb, actWs As Worksheet, lastR As Long, arrSh(), k As Long
Set actWs = ThisWorkbook.ActiveSheet
lastR = actWs.Range("A" & actWs.rows.count).End(xlUp).row
ReDim arrSh(ThisWorkbook.Sheets.count - 1)
cnt = 0
For i = 1 To Sheets.count
If Not ThisWorkbook.Sheets(i) Is actWs Then
xWb = Application.match(Sheets(i).Name, actWs.Range("A7:A" & lastR), 0)
If IsError(xWb) Then
arrSh(k) = CStr(ThisWorkbook.Sheets(i).Name): k = k + 1
cnt = cnt + 1
End If
End If
Next
ReDim Preserve arrSh(k - 1) 'keep only the filled array elements
Sheets(arrSh).Select 'You can replace 'Select' with 'Delete', if it returns correctly
If cnt = 0 Then
MsgBox "Not find the sheets to be seleted", vbInformation, "Kutools for Excel"
Else
MsgBox "Have deleted " & cnt & " worksheets"
End If
End Sub
It processes all existing values in column A:A, starting from the 7th row.
But I'm afraid that the range you try processing does not contain any existing sheet name...
In order to test the above supposition, please run the next test sub, which will place all existing sheets name in column B:B, starting from the 7th row. Then delete some rows and run the previous code, replacing "A" with "B" in lastR = actWs.Range("A" &... and actWs.Range("A7:A" & lastR). The code should select all missing sheets:
Sub testArraySheets()
Dim arrSh, ws As Worksheet, k As Long
ReDim arrSh(ActiveWorkbook.Sheets.count - 1)
For Each ws In ActiveWorkbook.Sheets
If Not ws Is ActiveSheet Then
arrSh(k) = ws.Name: k = k + 1
End If
Next
ActiveSheet.Range("B7").Resize(UBound(arrSh) + 1, 1).Value = Application.Transpose(arrSh)
End Sub

Excel VBA cut and paste a dynamic range of cells [duplicate]

I would like to delete the empty rows my ERP Quotation generates. I'm trying to go through the document (A1:Z50) and for each row where there is no data in the cells (A1-B1...Z1 = empty, A5-B5...Z5 = empty) I want to delete them.
I found this, but can't seem to configure it for me.
On Error Resume Next
Worksheet.Columns("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
How about
sub foo()
dim r As Range, rows As Long, i As Long
Set r = ActiveSheet.Range("A1:Z50")
rows = r.rows.Count
For i = rows To 1 Step (-1)
If WorksheetFunction.CountA(r.rows(i)) = 0 Then r.rows(i).Delete
Next
End Sub
Try this
Option Explicit
Sub Sample()
Dim i As Long
Dim DelRange As Range
On Error GoTo Whoa
Application.ScreenUpdating = False
For i = 1 To 50
If Application.WorksheetFunction.CountA(Range("A" & i & ":" & "Z" & i)) = 0 Then
If DelRange Is Nothing Then
Set DelRange = Range("A" & i & ":" & "Z" & i)
Else
Set DelRange = Union(DelRange, Range("A" & i & ":" & "Z" & i))
End If
End If
Next i
If Not DelRange Is Nothing Then DelRange.Delete shift:=xlUp
LetsContinue:
Application.ScreenUpdating = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume LetsContinue
End Sub
IF you want to delete the entire row then use this code
Option Explicit
Sub Sample()
Dim i As Long
Dim DelRange As Range
On Error GoTo Whoa
Application.ScreenUpdating = False
For i = 1 To 50
If Application.WorksheetFunction.CountA(Range("A" & i & ":" & "Z" & i)) = 0 Then
If DelRange Is Nothing Then
Set DelRange = Rows(i)
Else
Set DelRange = Union(DelRange, Rows(i))
End If
End If
Next i
If Not DelRange Is Nothing Then DelRange.Delete shift:=xlUp
LetsContinue:
Application.ScreenUpdating = True
Exit Sub
Whoa:
MsgBox Err.Description
Resume LetsContinue
End Sub
I know I am late to the party, but here is some code I wrote/use to do the job.
Sub DeleteERows()
Sheets("Sheet1").Select
Range("a2:A15000").Select
Selection.SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End Sub
for those who are intersted to remove "empty" and "blank" rows ( Ctrl + Shift + End going deep down of your worksheet ) .. here is my code.
It will find the last "real"row in each sheet and delete the remaining blank rows.
Function XLBlank()
For Each sh In ActiveWorkbook.Worksheets
sh.Activate
Cells(1, 1).Select
lRow = Cells.Find(What:="*", _
After:=Range("A1"), _
LookAt:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Range("A" & lRow + 1, Range("A1").SpecialCells(xlCellTypeLastCell).Address).Select
On Error Resume Next
Selection.EntireRow.SpecialCells(xlBlanks).EntireRow.Delete
Cells(1, 1).Select
Next
ActiveWorkbook.Save
ActiveWorkbook.Worksheets(1).Activate
End Function
Open VBA ( ALT + F11 ), Insert -> Module,
Copy past my code and launch it with F5.
Et voila :D
I have another one for the case when you want to delete only rows which are complete empty, but not single empty cells. It also works outside of Excel e.g. on accessing Excel by Access-VBA or VB6.
Public Sub DeleteEmptyRows(Sheet As Excel.Worksheet)
Dim Row As Range
Dim Index As Long
Dim Count As Long
If Sheet Is Nothing Then Exit Sub
' We are iterating across a collection where we delete elements on the way.
' So its safe to iterate from the end to the beginning to avoid index confusion.
For Index = Sheet.UsedRange.Rows.Count To 1 Step -1
Set Row = Sheet.UsedRange.Rows(Index)
' This construct is necessary because SpecialCells(xlCellTypeBlanks)
' always throws runtime errors if it doesn't find any empty cell.
Count = 0
On Error Resume Next
Count = Row.SpecialCells(xlCellTypeBlanks).Count
On Error GoTo 0
If Count = Row.Cells.Count Then Row.Delete xlUp
Next
End Sub
To make Alex K's answer slightly more dynamic you could use the code below:
Sub DeleteBlankRows()
Dim wks As Worksheet
Dim lngLastRow As Long, lngLastCol As Long, lngIdx As Long, _
lngColCounter As Long
Dim blnAllBlank As Boolean
Dim UserInputSheet As String
UserInputSheet = Application.InputBox("Enter the name of the sheet which you wish to remove empty rows from")
Set wks = Worksheets(UserInputSheet)
With wks
'Now that our sheet is defined, we'll find the last row and last column
lngLastRow = .Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious).Row
lngLastCol = .Cells.Find(What:="*", LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious).Column
'Since we need to delete rows, we start from the bottom and move up
For lngIdx = lngLastRow To 1 Step -1
'Start by setting a flag to immediately stop checking
'if a cell is NOT blank and initializing the column counter
blnAllBlank = True
lngColCounter = 2
'Check cells from left to right while the flag is True
'and the we are within the farthest-right column
While blnAllBlank And lngColCounter <= lngLastCol
'If the cell is NOT blank, trip the flag and exit the loop
If .Cells(lngIdx, lngColCounter) <> "" Then
blnAllBlank = False
Else
lngColCounter = lngColCounter + 1
End If
Wend
'Delete the row if the blnBlank variable is True
If blnAllBlank Then
.rows(lngIdx).delete
End If
Next lngIdx
End With
MsgBox "Blank rows have been deleted."
End Sub
This was sourced from this website and then slightly adapted to allow the user to choose which worksheet they want to empty rows removed from.
In order to have the On Error Resume function work you must declare the workbook and worksheet values as such
On Error Resume Next
ActiveWorkbook.Worksheets("Sheet Name").Columns("A:A").SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
I had the same issue and this eliminated all the empty rows without the need to implement a For loop.
This worked great for me (you can adjust lastrow and lastcol as needed):
Sub delete_rows_blank2()
t = 1
lastrow = ActiveSheet.UsedRange.Rows.Count
lastcol = ActiveSheet.UsedRange.Columns.Count
Do Until t = lastrow
For j = 1 To lastcol
'This only checks the first column because the "Else" statement below will skip to the next row if the first column has content.
If Cells(t, j) = "" Then
j = j + 1
If j = lastcol Then
Rows(t).Delete
t = t + 1
End If
Else
'Note that doing this row skip, may prevent user from checking other columns for blanks.
t = t + 1
End If
Next
Loop
End Sub
Here is the quickest way to Delete all blank Rows ( based on one Columns )
Dim lstRow as integet, ws as worksheet
Set ws = ThisWorkbook.Sheets("NameOfSheet")
With ws
lstRow = .Cells(Rows.Count, "B").End(xlUp).Row ' Or Rows.Count "B", "C" or "A" depends
.Range("A1:E" & lstRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
End with

Adding a ListRow into a table of a protected worksheet

I want to add data to last row in each table in each worksheet when the worksheet is protected.
I have this code in ThisWorkbook to protect the worksheets
Private Sub Workbook_Open()
Dim wSheet As Worksheet
For Each wSheet In Worksheets
wSheet.Protect Password:="Secret", _
UserInterFaceOnly:=True
Next wSheet
End Sub
and the following code to add the data. It throws
Error 1004 "Application-defined or Object-defined error"
at the Set newrow1 = tbl.ListRows.Add when the worksheet is protected.
Sub AddDataToTable()
Application.ScreenUpdating = False
Dim MyValue As String
Dim sh As Worksheet
Dim ws1 As Worksheet
Dim ws2 As Worksheet
Dim ws3 As Worksheet
Dim ws4 As Worksheet
Dim ws5 As Worksheet
Set ws1 = Sheets("Setting")
Set ws2 = Sheets("R_Buy")
Set ws3 = Sheets("R_Sell")
Set ws4 = Sheets("S_Buy")
Set ws5 = Sheets("S_Sell")
Dim tbl As ListObject
Dim tb2 As ListObject
Dim tb3 As ListObject
Dim tb4 As ListObject
Dim tb5 As ListObject
Set tbl = ws1.ListObjects("T_Setting")
Set tb2 = ws2.ListObjects("T_R_Buy")
Set tb3 = ws3.ListObjects("T_R_Sell")
Set tb4 = ws4.ListObjects("T_S_Buy")
Set tb5 = ws5.ListObjects("T_S_Sell")
Dim newrow1 As ListRow
Dim newrow2 As ListRow
Dim newrow3 As ListRow
Dim newrow4 As ListRow
Dim newrow5 As ListRow
MyValue = InputBox("Add To Table, this cannot be undone")
'check if user clicked Cancel button and, if appropriate, execute statements
If StrPtr(MyValue) = 0 Then
'display message box confirming that user clicked Cancel button
MsgBox "You clicked the Cancel button"
'check if user entered no input and, if appropriate, execute statements
ElseIf MyValue = "" Then
'display message box confirming that user entered no input
MsgBox "There is no Text Input"
Else
Set newrow1 = tbl.ListRows.Add
With newrow1
.Range(1) = MyValue
End With
Set newrow2 = tb2.ListRows.Add
With newrow2
.Range(1) = MyValue
End With
Set newrow3 = tb3.ListRows.Add
With newrow3
.Range(1) = MyValue
End With
Set newrow4 = tb4.ListRows.Add
With newrow4
.Range(1) = MyValue
End With
Set newrow5 = tb5.ListRows.Add
With newrow5
.Range(1) = MyValue
End With
End If
Application.ScreenUpdating = True
End Sub
That's an issue with Excel that it doesn't allow to edit tables in UserInterFaceOnly:=True mode. Unfortunately, the only workaround I've found is to unprotect before any table methods are applied and then reprotect after:
.Unprotect Password:=SHEET_PW 'unprotect sheet
'edit table
.Protect Password:=SHEET_PW, UserInterFaceOnly:=True 'reprotect
Additionally I suggest the following improvement to shorten your code:
Use arrays Dim tbl(1 To 5) instead of multiple variables tbl1, tbl2, tbl3, …
Or better use an array to list your worksheet names only.
Use more descriptive variable names (makes your life easier to maintain and read the code)
If your table names are always T_ followed by the worksheet name you can easily generate them out of your worksheet name.
Use a constant for your worksheet password SHEET_PW to have it stored in only one place (easier to change, prevents typos).
Use loops to do repetitive things.
So we end up with:
Option Explicit
Const SHEET_PW As String = "Secret" 'global password for protecting worksheets
Public Sub AddDataToTableImproved()
Dim AddValue As String
AddValue = InputBox("Add To Table, this cannot be undone")
If StrPtr(AddValue) = 0 Then 'cancel button
MsgBox "You clicked the Cancel button"
Exit Sub
ElseIf AddValue = "" Then 'no input
MsgBox "There is no Text Input"
Exit Sub
End If
Dim NewRow As ListRow
Dim SheetNameList() As Variant
SheetNameList = Array("Setting", "R_Buy", "R_Sell", "S_Buy", "S_Sell")
Dim SheetName As Variant
For Each SheetName In SheetNameList
With ThisWorkbook.Worksheets(SheetName)
.Unprotect Password:=SHEET_PW 'unprotect sheet
Set NewRow = .ListObjects("T_" & SheetName).ListRows.Add
NewRow.Range(1) = AddValue
.Protect Password:=SHEET_PW, UserInterFaceOnly:=True 'reprotect it
End With
Next SheetName
End Sub
A bit late to help the original OP but hopefully this will help other readers.
There is indeed an issue with the ListObject functionality when the worksheet is protected even if the UserInterFaceOnly flag is set to True.
However, we can still use the Range and Application functionality and we can actually work around most of the use cases with the exception of 2 edge cases:
We want to insert immediately after the header row AND the sheet is protected AND the headers are off (.ShowHeaders is False) - I don't think there is any solution to this but to be honest I wonder why would one have the headers off. Not to mention it's a really rare case to meet all 3 criterias.
The table has no rows AND the sheet is protected AND the headers are off. In this case the special 'insert' row cannot easily be turned into a 'listrow' but it can be done with a few column and row inserts - not worth the trouble though as this is potentially rare in real life use.
Here is the code that I came up with:
Option Explicit
Option Private Module
Private Const MODULE_NAME As String = "LibExcelListObjects"
'*******************************************************************************
'Adds rows to a ListObject and returns the corresponding added Range
'Parameters:
' - tbl: the table to add rows to
' - [rowsToAdd]: the number of rows to add. Default is 1
' - [startRow]: the row index from where to start adding. Default is 0 in
' which case the rows would be appended at the end of the table
' - [doEntireSheetRow]:
' * TRUE - adds entire rows including left and right of the target table
' * FALSE - adds rows only below the table bounds shifting down (default)
'Raises error:
' - 5: if 'rowsToAdd' is less than 1
' - 9: if 'startRow' is invalid
' - 91: if 'tbl' is not set
' - 1004: if adding rows failed due to worksheet being protected while the
' UserInterfaceOnly flag is set to False
'*******************************************************************************
Public Function AddListRows(ByVal tbl As ListObject _
, Optional ByVal rowsToAdd As Long = 1 _
, Optional ByVal startRow As Long = 0 _
, Optional ByVal doEntireSheetRow As Boolean = False _
) As Range
Const fullMethodName As String = MODULE_NAME & ".AddListRows"
Dim isSuccess As Boolean
'
If tbl Is Nothing Then
Err.Raise 91, fullMethodName, "Table object not set"
ElseIf startRow < 0 Or startRow > tbl.ListRows.Count + 1 Then
Err.Raise 9, fullMethodName, "Invalid start row index"
ElseIf rowsToAdd < 1 Then
Err.Raise 5, fullMethodName, "Invalid number of rows to add"
End If
If startRow = 0 Then startRow = tbl.ListRows.Count + 1
'
If startRow = tbl.ListRows.Count + 1 Then
isSuccess = AppendListRows(tbl, rowsToAdd, doEntireSheetRow)
Else
isSuccess = InsertListRows(tbl, rowsToAdd, startRow, doEntireSheetRow)
End If
If Not isSuccess Then
If tbl.Parent.ProtectContents And Not tbl.Parent.ProtectionMode Then
Err.Raise 1004, fullMethodName, "Parent sheet is macro protected"
Else
Err.Raise 5, fullMethodName, "Cannot append rows"
End If
End If
Set AddListRows = tbl.ListRows(startRow).Range.Resize(RowSize:=rowsToAdd)
End Function
'*******************************************************************************
'Utility for 'AddListRows' method
'Inserts rows into a ListObject. Does not append!
'*******************************************************************************
Private Function InsertListRows(ByVal tbl As ListObject _
, ByVal rowsToInsert As Long _
, ByVal startRow As Long _
, ByVal doEntireSheetRow As Boolean) As Boolean
Dim rngInsert As Range
Dim fOrigin As XlInsertFormatOrigin: fOrigin = xlFormatFromLeftOrAbove
Dim needsHeaders As Boolean
'
If startRow = 1 Then
If Not tbl.ShowHeaders Then
If tbl.Parent.ProtectContents Then
Exit Function 'Not sure possible without headers
Else
needsHeaders = True
End If
End If
fOrigin = xlFormatFromRightOrBelow
End If
'
Set rngInsert = tbl.ListRows(startRow).Range.Resize(RowSize:=rowsToInsert)
If doEntireSheetRow Then Set rngInsert = rngInsert.EntireRow
'
On Error Resume Next
If needsHeaders Then tbl.ShowHeaders = True
rngInsert.Insert xlShiftDown, fOrigin
If needsHeaders Then tbl.ShowHeaders = False
InsertListRows = (Err.Number = 0)
On Error GoTo 0
End Function
'*******************************************************************************
'Utility for 'AddListRows' method
'Appends rows to the bottom of a ListObject. Does not insert!
'*******************************************************************************
Private Function AppendListRows(ByVal tbl As ListObject _
, ByVal rowsToAppend As Long _
, ByVal doEntireSheetRow As Boolean) As Boolean
If tbl.ListRows.Count = 0 Then
If Not UpgradeInsertRow(tbl) Then Exit Function
If rowsToAppend = 1 Then
AppendListRows = True
Exit Function
End If
rowsToAppend = rowsToAppend - 1
End If
'
Dim rngToAppend As Range
Dim isProtected As Boolean: isProtected = tbl.Parent.ProtectContents
'
On Error GoTo ErrorHandler
If isProtected And tbl.ShowTotals Then
Set rngToAppend = tbl.TotalsRowRange
ElseIf isProtected Then
Set rngToAppend = AutoExpandOneRow(tbl)
Else
Set rngToAppend = tbl.Range.Rows(tbl.Range.Rows.Count + 1)
End If
'
Set rngToAppend = rngToAppend.Resize(RowSize:=rowsToAppend)
If doEntireSheetRow Then Set rngToAppend = rngToAppend.EntireRow
rngToAppend.Insert xlShiftDown, xlFormatFromLeftOrAbove
'
If isProtected And tbl.ShowTotals Then 'Fix formatting
tbl.ListRows(1).Range.Copy
With tbl.ListRows(tbl.ListRows.Count - rowsToAppend + 1).Range
.Resize(RowSize:=rowsToAppend).PasteSpecial xlPasteFormats
End With
ElseIf isProtected Then 'Delete the autoExpand row
tbl.ListRows(tbl.ListRows.Count).Range.Delete xlShiftUp
Else 'Resize table
tbl.Resize tbl.Range.Resize(tbl.Range.Rows.Count + rowsToAppend)
End If
AppendListRows = True
Exit Function
ErrorHandler:
AppendListRows = False
End Function
'*******************************************************************************
'Utility for 'AppendListRows' method
'Transforms the Insert row into a usable ListRow
'*******************************************************************************
Private Function UpgradeInsertRow(ByVal tbl As ListObject) As Boolean
If tbl.InsertRowRange Is Nothing Then Exit Function
If tbl.Parent.ProtectContents And Not tbl.ShowHeaders Then
Exit Function 'Not implemented - can be done using a few inserts
Else
Dim needsHeaders As Boolean: needsHeaders = Not tbl.ShowHeaders
'
If needsHeaders Then tbl.ShowHeaders = True
tbl.InsertRowRange.Insert xlShiftDown, xlFormatFromLeftOrAbove
If needsHeaders Then tbl.ShowHeaders = False
End If
UpgradeInsertRow = True
End Function
'*******************************************************************************
'Utility for 'AppendListRows' method
'Adds one row via auto expand if the worksheet is protected and totals are off
'*******************************************************************************
Private Function AutoExpandOneRow(ByVal tbl As ListObject) As Range
If Not tbl.Parent.ProtectContents Then Exit Function
If tbl.ShowTotals Then Exit Function
'
Dim ac As AutoCorrect: Set ac = Application.AutoCorrect
Dim isAutoExpand As Boolean: isAutoExpand = ac.AutoExpandListRange
Dim tempRow As Range: Set tempRow = tbl.Range.Rows(tbl.Range.Rows.Count + 1)
'
If Not isAutoExpand Then ac.AutoExpandListRange = True
tempRow.Insert xlShiftDown, xlFormatFromLeftOrAbove
Set AutoExpandOneRow = tempRow.Offset(-1, 0)
Const arbitraryValue As Long = 1 'Must not be Empty/Null/""
AutoExpandOneRow.Value2 = arbitraryValue 'AutoExpand is triggered
If Not isAutoExpand Then ac.AutoExpandListRange = False 'Revert if needed
End Function
Assuming tbl is a variable holding the table, we can use the above like this:
AddListRows tbl 'Adds 1 row at the end
AddListRows tbl, 5 'Adds 5 rows at the end
AddListRows tbl, 3, 2 'Inserts 3 rows at index 2
AddListRows tbl, 1, 3, True 'Insert one row at index 3 but for the whole sheet
As long as the UserInterfaceOnly flag is set to True the above will work except the 2 edge cases I mentioned at the beginning of the answer. Of course, the operation would fail if there is another ListObject immediately below the table we want to insert into but that would fail anyway even if the sheet was unprotected.
One nice advantage is that the AddListRows method above returns the range that was inserted so that it can be used to write data immediately after the rows were added.

Connect newly added Sheet to existing one

This is my first post in Stack Overflow so any mistake I make please just ignore.
So i made an button which runs the macro of an application inputbox, the name you enter in the inputbox will create a new sheet with the name you entered, it also will create a table on the new sheet. The name you put on the inputbox are the clients that newly came so i will have specific sheet with table for every client that comes.
On the other hand I got the Workers which will receive incomes from clients, I Got 4 Workers which have their own Sheet and Table of Incomes and Outcomes.
Now the question i am getting to is that, is it possible to creade a code on VBA that will say: If on the new sheet (inside the table, specificly: K8:K23, K28:K43, K49:K64) the name of the Worker is inserted, copy the name of the client and paste it into the existing sheet of the Worker.
The code i tried but did not work: (Only Check the First Sub and the end of line, the between code is just a bunch of macro for table to be created, that parts work, the problem of my code which is located at the end is that it does nothing, and yes I did an commend to the codes on purpose)
Sub KerkimiKlientit()
Dim EmriKlientit As String
Dim rng As Range, cel As Range
Dim OutPut As Integer
retry:
EmriKlientit = Application.InputBox("Shkruani Emrin e Klientit", "Kerkimi")
If Trim(EmriKlientit) <> "" Then
With Sheets("Hyrjet").Range("B10:B200")
Set rng = .Find(What:=EmriKlientit, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not rng Is Nothing Then
sheet:
Flag = 0
Count = ActiveWorkbook.Worksheets.Count
For i = 1 To Count
WS_Name = ActiveWorkbook.Worksheets(i).Name
If WS_Name = EmriKlientit Then Flag = 1
Next i
If Flag = 1 Then
ActiveWorkbook.Sheets(EmriKlientit).Activate
Exit Sub
Else
Sheets.Add(, Sheets(Sheets.Count)).Name = EmriKlientit
Call KrijimiTabeles(EmriKlientit)
Exit Sub
End If
Else
OutPut = MsgBox("Klienti nuk u gjet", vbRetryCancel + vbInformation, "Provoni Perseri")
If (OutPut = vbRetry) Then
GoTo retry:
ElseIf (OutPut = vbCancel) Then
Exit Sub
End If
Exit Sub
End If
End With
End If
If userInputValue = "" Then
OutPut = MsgBox("Rubrika e Emrit e zbrazet", vbRetryCancel + vbExclamation, "Gabim")
If (OutPut = vbRetry) Then
GoTo retry:
ElseIf (OutPut = vbCancel) Then
Exit Sub
End If
Else
GoTo retry:
End If
End Sub
Sub KrijimiTabeles(EmriKlientit As String)
'
' KrijimiTabeles Macro
'
'This was just an middle code, it was too long so I did not paste it. Not an important part tho.
'This is the part that does not work, it just does nothing for some reason, there are multiple codes here and I tried them all.
'Sub Formula(EmriKlientit As String, ByVal Target As Range)
'ActiveWorkbook.Sheets(EmriKlientit).Activate
'If Not Application.Intersect(Range("K8:K23"), Range(Target.Adress)) Is Nothing Then
'Call Formula1
'End If
'End Sub
'Dim LR As Long, i As Long
'Application.ScreenUpdating = False
'Dim Rng As Range
'For Each Rng In Range("K8:K23")
'Select Case Rng.Value
'Case "M"
'Worksheets(EmriKlientit).Range("K2").Copy
'Worksheets("Mustafa").Range("K6").PasteSpecial Paste:=xlPasteFormulas
'End Select
'Next Rng
'Application.ScreenUpdating = True
'For Each cel In Rng
'If cel.Value = "M" Then
'Worksheets(EmriKlientit).Range("K2").Copy
'Worksheets("Mustafa").Range("K6").PasteSpecial Paste:=xlPasteFormulas
'End If
'Next cel
'ActiveWorkbook.Sheets(EmriKlientit).Activate
'If Not Application.Intersect(Range("K8:K23"), Range(Rng.Adress)) Is Nothing Then
'With Sheets(EmriKlientit)
'With .Range("K8:K23")
'If .Text = "M" Then
'Worksheets(EmriKlientit).Range("K2").Copy
'Worksheets("Mustafa").Range("K6").PasteSpecial Paste:=xlPasteFormulas
'End If
'End With
'End With
'End If
'Flag = 0
'Count = ActiveWorkbook.Worksheets.Count
'For i = 1 To Count
'WS_Name = ActiveWorkbook.Worksheets(i).Name
'If WS_Name = EmriKlientit Then Flag = 1
'Next i
'If Flag = 1 Then
'ActiveWorkbook.Sheets(EmriKlientit).Activate
'For Each Cell In Sheets(EmriKllientit).Range("K8:K23")
'If Cell.Value = "M" Then
'Range("K2").Copy
'Worksheets("Mustafa").Range("K6").PasteSpecial Paste:=xlPasteFormulas
'End If
'Next
'End If
End Sub
Thank you
I hope I was clear enough,
Any help would be appreciated.
Welcome to StackOverflow - i agree that your question can be a bit more specific...
I think what you are trying to achieve is something between this lines:
Dim wsClient As Worksheet, wsMustafa As Worksheet
Dim i As Long
Dim fRow As Long, lRow As Long
Set wsClient = ActiveWorkbook.Sheets("Client")
Set wsMustafa= ActiveWorkbook.Sheets("Mustafa")
'you can assign this through better ways, but to start with...
fRow = 8
lRow = 23
For i = fRow To lRow
If wsClient.Range("K" & i).Value = "M" Then
wsMustafa.Range("K6").Value = wsClient.Range("K" & i).Value 'or .Formula if that's what you want
End If
Next i
Hope this helps, good luck.

Resources