Adding msgbox if my pivot table has empty cells - excel

enter image description hereI have an Excel workbook that runs a macro and in the end displays everything in a pivot table
I am trying to add a msgbox when my pivot table has an empty cell (at the end of my macro)
I already did the conditional formatting version(color blank cells red) and it works fine, but the client wants a msgbox to alert him.
I found a IsEmpty command that should work but I cant seem to make it look only inside said pivot table.
Here is what I tried:
Sub IsEmpty()
If IsEmpty(ActiveSheet.Range("PivotTables(1)")) = True Then
'Cell A2 is not blank
MsgBox "Cell A2 is empty"
Else
End If
End Sub
I'm sure the way my If statement is written is false. Just cant seem to find the right syntax.
Thanks in advance
Picture added; I want the macro to target pivot's C column. However, you cant know which cell will be empty or how long the list will continue.
And if just make Excel check a broad spectrum(c2:c300), there will always be en empty cell after the pivot table is finished.
There might be a loop you can create but its way over my current skill set.
The pivot table's name is "PivotTable2"
Is there a to search only in the pivot table's column c for empty cells?

Please consider the capabilities of the function below. It will return True or False depending upon the count of items in columns A and C. In column A text, number or function is counted. In column C there must be a number in each cell. If both counts are the same the function returns True. Either count can be further refined if there are exceptions which the current function doesn't correction evaluate.
Function IsComplete() As Boolean
' 025
Dim Rng As Range
With ThisWorkbook.Sheets("PivotTables(1)") ' change to suit
' set a range from A3 to end of column A
Set Rng = .Range(.Cells(3, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
With Application.WorksheetFunction
IsComplete = (.CountA(Rng) = .Count(Rng.Offset(0, 2)))
End With
End Function
You can use code to call this function and display a message box for True and another one if the function returns False. The code can be hitched to a button on your sheet, anywhere in your workbook.
Sub CommandButton1_Click()
Dim Txt As String
If IsComplete Then
Txt = "The pivot table was created without mistakes."
Else
Txt = "Some data are missing in the pivot table."
End If
MsgBox Txt, vbInformation, "Action report"
End Sub
You can also call the function as a UDF and display True or False in a cell of any sheet in your workbook. The UDF call would be like =IsComplete(). You might also embed the UDF call in an IF condition and display another text on your worksheet.
=IF(IsComplete(),"All's well","Missing Item")
In fact, you could slightly modify the function to return the difference between one count and the other and display "1 item missing". The possibilities are endless because the function is so versatile.

Related

How to alternate row color in a table when cell value changes?

I have a spreadsheet that brings in a table of data via Power Query.
Every time there is a refresh, the table length may change.
I need columns C and D to alternate highlight colors when the value is not the same as the previous row.
How the table should look each time it is refreshed through Power Query and the VBA code runs.
(1) Attempt with conditional formatting:
(Note: This will work correctly only if a value cannot appear later down that list).
Create a rule (or two rules, to be precise) based on a formula. According to your screenshot, I assume that your data starts at row 3 and you want to look at column C.
There is a rather easy formula that you can use to count the number of unique values of a list. The base formula was "borrowed" from ExcelJet and is =SUMPRODUCT(1/COUNTIF(data,data)). The trick now is that you look to the range from the beginning of the list to the actual row by using the range C$3:C3. If you copy the formula down, the start row remains while the end row is changed. Now simple put a IsOdd resp IsEven around the formula.
So the formula is =ISODD(SUMPRODUCT(1/COUNTIF(C$3:C3,C$3:C3))) for the "green" rows and =ISEVEN(SUMPRODUCT(1/COUNTIF(C$3:C3,C$3:C3))) for the yellow. Apply the rule to the range =$C$3:$C$1048576
However, I don't know if this conditional formatting will "survive" an update of the query.
(2)
Formatting with VBA is simple. The following code formats one column of an table (a table in VBA is the type ListObject. Pass the listobject and the column number as parameter:
Sub ColorRows(table As ListObject, columnNumber As Long)
Dim cell As Range, isOdd As Boolean
For Each cell In table.DataBodyRange.Columns(columnNumber).Cells
With cell
If .Offset(-1, 0) <> .Value Then isOdd = Not isOdd
' On a standard Office color scheme, 10 is kind of green and 8 is a dirty yellow
.Interior.ThemeColor = IIf(isOdd, 10, 8)
.Interior.TintAndShade = 0.8
End With
Next
End Sub
This is how the call could look like (adapt the sheet and the listObject to your needs):
Sub test()
ColorRows ThisWorkbook.Sheets(1).ListObjects(1), 3
End Sub
Now calling this code automatically is a different story and unfortunately rather complicated - if you want/need, try https://stackoverflow.com/search?q=vba+QueryTable+After+Refresh for some insights. An easy alternative is to trigger the formatting manually, eg by placing a button (or a shape) on your sheet that calls the code.
The VBA to apply the format condition for the alternating coloring would be:
Public Sub alternatingColorSizeAndKind(rg As Range)
Dim fc As FormatCondition
With rg.FormatConditions
.Delete
Set fc = .Add(xlExpression, , "=($C1=$C2)+($C2=$C3)")
fc.Interior.Color = 14348258
Set fc = .Add(xlExpression, , "=($C1<>$C2)")
fc.Interior.Color = 13431551
End With
End Sub
You have to pass the range of your table to this sub.
If you have a listobject/table then you call it like this:
Public Sub update()
Dim lo As ListObject
'>>> adjust the names to your needs
Set lo = ThisWorkbook.Worksheets("Sheet1").ListObjects("Pull_Data")
alternatingColorSizeAndKind lo.DataBodyRange
End Sub

Warn if blank/empty cells

I'm trying to pop up a warning dialog if one of the cells in a range is blank.
Excel is popping up the warning when a cell is populated by a data validation drop down menu.
The code works on a range that doesn't contain data validation drop downs.
All data are strings and the cells are formatted as "General".
ActiveSheet.Range("I3:I10").Select
For Each cell In Selection
If cell.Value = "" Then
If MsgBox("Customer information missing. Okay to proceed; Cancel to stop and fill in missing information.", vbOKCancel) = vbCancel Then
Exit Sub
Else
Exit For
End If
End If
Next
The issue seems to stem from cells being merged across multiple columns, so Excel is checking each cell I3:K10 and finding J3:K10 blank. Unmerging the cells isn't an option.
If a cell is set up with data validation using a list and one of the cells in the list range is blank, the cell will be considered blank even if the user has selected the blank cell from the drop-down. However, if you also want to check if the cell is empty and does not have data validation, you can use the following (thanks to Determine if cell contains data validation)
Dim blnValidation As Boolean
Dim cell As Range
ActiveSheet.Range("I3:I10").Select
For Each cell In Selection
If cell.Value = "" Then
blnValidation = False
On Error Resume Next
blnValidation = Not IsNull(cell.Validation.Type)
On Error GoTo 0
If Not blnValidation Then
If MsgBox("Customer information missing. Okay to proceed; Cancel to stop and fill in missing information.", vbOKCancel) = vbCancel Then
Exit Sub
Else
Exit For
End If
End If
End If
Next
So, I was wrong with my initial guess, but the cure still would've worked.
How to avoid using Select in Excel VBA
The selection is actually Range("I3:K10"). So after it checks column I it moves onto Column J and then K
There a COUNTBLANK function but in this case you're probably better off with the COUNT Application.WorksheetFunction.
You could replace your loop with:
If Application.WorksheetFunction.Count(Range("I3:I10")) < 8 Then
'missing data - notify user here
End If

Formula to hide rows based on the value of a cell

I have a worksheet that contains the names of all managers and their employees, ideally the way this sheet needs to work is that there is a drop down in the top left and when a manager selects their name, all rows that don't have their name against, are hidden, so only their team is shown.
I know auto filtering and having them choose their name would be the easiest way and is a good option to fall back on, but I'm hoping there is a way to do this with VBA or a formula to just hide rows when its not their team when they select their name in the drop down. As i'm trying to create something that's quite slick and looks nice
I did try to do something around having a helper cell to display true and false if the names matched, but came a bit stuck at this point. Tried using the code below, but it doesn't seem to actually be doing anything. Column with TRUE/FALSE is in Col A
Sub TEST()
Dim cell As Range
Application.ScreenUpdating = False
Application.EnableEvents = False
For Each cell In Range("A4:A34")
If cell.Value = "FALSE" Then
cell.EntireRow.Hidden = True
Else
cell.EntireRow.Hidden = False
End If
Next
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Any ideas on how to do this without just using autofilter would be great
Given the following assumptions:
Drop down with Manager name is in cell A1
Column listing manager name for each row is in column A
Data set starts in row 5
Column A is contiguous with no blank spaces
Place the following code into the Worksheet module of the data sheet and change assumptions to fit your data set.
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address = "$A$1" and Target.Cells.Count = 1 Then
Application.ScreenUpdating = False
Range("A5:A1000").EntireRow.Hidden = False
Dim mgrList as Range
Set mgrList = Range(Range("A5"),Range("A5").End(xlDown))
Dim mgrCheck as Range
For each mgrCheck in mgrList
mgrCheck.EntireRow.Hidden = mgrCheck <> Target
Next
End If
End Sub
Use an if then else statement with a call that shows/hides the rows that you'd like to show.
If Range("A1").Value = "John Snow" Then
Call Show_John_Snow
Else
If Range("A1").Value = "Daenerys Targaryen" Then
Call Show_Daenerys
Else....
'subroutine
Show_John_Snow
Rows("17:20").EntireRow.Hidden = True 'hide others
Rows("21:53").EntireRow.Hidden = False 'show John Snow
Rows("54:75").EntireRow.Hidden = True 'hide others
I have this data, in which I have Headers at A3:D3, data starting from row 4 to 99.
I tried applying Autofilter, check if this one works for you.
Sub test()
Range("A3:D3").Select
Selection.AutoFilter
ActiveSheet.Range("A3:D99").AutoFilter Field:=2, Criteria1:="0"
ActiveSheet.Range("A3:D99").AutoFilter Field:=2, Criteria1:="1"
End Sub
Here, I selected option named "0" from drop-down filter from Field-2, that is Range A4, and as you told, other cells automatically gets hidden, and the cells corresponding to that criteria only gets visible.
Also I tried with other option "1".
This seems a very difficult or involved way to do this, I have to show students their results without them seeing other students results.
So, one sheet has all the data and on a "front" sheet I call the relevant data for the particular student using index() and match(). Each student has an ID number which is entered, then for confirmation the name is returned then the relevant grades.

How to autopopulate excel column based on dropdown list selection from another column

I have a spreadsheet that has two buttons - To retrieve rows from a sql table using a macro and another one to update data changes back to the table from excel. I have also attached an image here for reference. The table columns are EmpID, EName, Grouping, CCNum,CCName, ResTypeNum, ResName and Status.
Now to update changes, I have drop down lists for CCName and ResName. I would like the ResTypeNum to change automatically whenever the value in ResName column from dropdown list changes. Using Vlookup doesn't seem to work as the formula gets wiped out every time I click on the Retrieve button to refresh data. Also, I have to drag down the formula which I don't want but instead the value in ResTypeNum should automatically update whenever the ResName column is changed. I would appreciate any new ideas to make this work.
Thank you,
Hema
Assumptions:
First value is in A4
ResName column is G
Sheet with data validation list and corresponding code in sheet "ResNameSheet"
In the tables sheet event module you place the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Column = 7 And Target.Row > 3 Then
If Target.Value2 = "" Then
Target.Offset(0, -1).Value2 = ""
Exit Sub
End If
Dim rngDataValidation As Range
Dim rngRow As Range
Set rngDataValidation = ThisWorkbook.Sheets("ResNameSheet").UsedRange
For Each rngRow In rngDataValidation.Rows
If rngRow.Cells(1, 1).Value2 = Target.Value2 Then
Target.Offset(0, -1).Value2 = rngRow.Cells(1, 2).Value2
End If
Next
End If
End Sub
Explaining how the code works:
Fires on changes to the sheet
checks if changes are in column G (7) and that it occurs below the header row (3)
Checks that the change was not deleting from column G, if it is it clears all values on the corresponding column F
Loops through the Rows collection in the range with ResName list
Checks if values match
If it does it writes the corresponding code to the column to left of Target
Hope this helps.

Moving Rows to another sheet in a workbook

I need Help!
I am not well versed in VBA or Macros but i cannot find any other way to accomplish what i need to do without using it.
I have a sheet which i will be using to track Purchase orders, and what i need to do is; when i have a row in sheet 1 (Purchase Orders) which has been recieved i.e. the date of receipt has been recorded in column H i need for the entire row to be cut and pasted into sheet 2 (Received orders).
The header takes up the first 7 rows the rows, so i need the macro to look at rows 8-54. Once the received items are removed from sheet 1, i need the row to also be deleted or preferably for the list to be sorted by column A moving the now empty row which has been cut from open for a future entry.
Any help would be greatly appreciated.
The "Record Macro" feature should be enough to do the task you describe.. In Excel 2007, go to the Developer tab in the Ribbon, and select "Record Macro", and perform exactly the steps you are describing. It will record the equivalent VBA code, which you can then execute - or tweak/modify.
I tested this out, here's one way to do it:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim receivedDate As Range, nextOpen As Range, isect As Range
Set receivedDate = Sheet1.Range("H8:H54")
Set isect = Application.Intersect(Target, receivedDate)
If Not (isect Is Nothing) And IsDate(Target) = True Then
Set nextOpen = Sheet2.Range("A1").End(xlDown).Offset(1, 0)
Target.EntireRow.Copy Destination:=nextOpen.EntireRow
Target.EntireRow.Delete
End If
Application.EnableEvents = True
End Sub
This would be pasted into the Sheet1 code. Any time a cell is changed on sheet1, the code checks to see if it's in the critical range that you specified. (H8:H54) If it is, it then checks to see if it's a date. If it is, it then copies the entire row, puts it in the next open row on Sheet2, and deletes the original row. The cells below it will get shifted up so there are no gaps.
Since the code functions on a cell changing event, it disables "Application.EnableEvents" in order to avoid a loop of changing a cell to call an event which changes a cell to call an event... etc.

Resources