How to make multiple pivotitem invisible in Excel Vba - vba

I have a Pivot table in sheet"EX". In pivot "Report Filter" field i have "Country Code" which contain 200 countries. I want to remove (Making invisible) more than 1 countries from that filter using InputBox. I used the code below and it is not working. It is not coming to "If InStr" line. Help me
Sub Removecountries()
Dim str1 As Variant
Dim Data As Variant
Dim ws As Worksheet
Set ws = Sheets("Ex")
str1 = Application.InputBox("Enter the Country - comma separated")
If str1 = False Then
MsgBox "Please Enter one Country", , "Filter Country"
Exit Sub
Else
If InStr(1, str1, ",") > 0 Then
Data = Split(str1, ",")
With ws.PivotTables("RemoveTable").PivotFields("Country Code").PivotItems(Data(0)).Visible = False
End With
End If
End If
End Sub

I've just tested the following and it seems to work, the issue seems to be when you only enter one item in the inputbox: (Before you try make sure you edit the "ws.PivotTable" as I changed the name when testing it)
Sub Removecountries()
Dim str1 As Variant
Dim Data As Variant
Dim ws As Worksheet
Set ws = Sheets("Ex")
str1 = Application.InputBox("Enter the Country - comma separated")
If str1 = False Then
MsgBox "Please Enter one Country", , "Filter Country"
Exit Sub
Else
ws.PivotTables("PivotTable1").PivotFields("CountryCode").ClearAllFilters
If InStr(1, str1, ",") > 0 Then
Data = Split(str1, ",")
For i = LBound(Data) To UBound(Data)
ws.PivotTables("PivotTable1").PivotFields("CountryCode").PivotItems(Data(i)).Visible = False
Next i
Else
ws.PivotTables("PivotTable1").PivotFields("CountryCode").PivotItems(str1).Visible = False
End If
End If
End Sub

Related

VBA search for value on next sheet

is there I way for searching a value on the next sheet (ActiveSheet.Next.Activate) without jumping on to it?
Here the whole Code:
the problem is, it jumps to the next sheet even if there is no searched value.
Dim ws As Worksheet
Dim Loc As Range
Dim StrVal As String
Dim StrRep As String
Dim i As Integer
Private Sub CommandButton1_Click()
i = 1
Call Replacing
End Sub
Private Sub CommandButton2_Click()
i = 2
Call Replacing
End Sub
Public Sub Replacing()
StrVal = Userform1.Textbox1.Text
StrRep = Me.Textbox1.Text
if Trim(StrVal) = "" Then Exit Sub
Dim fstAddress As String
Dim nxtAddress As String
For Each ws In ThisWorkbook.Worksheets
With ws
Set Loc = .Cells.Find(what:=StrVal)
fstAddress = Loc.Address
If Not Loc Is Nothing Then
If Not StrRep = "" And i = 1 Then
Loc.Value = StrRep
Set Loc = .Cells.FindNext(Loc)
ElseIf i = 2 Then Set Loc = Range(ActiveCell.Address)
Set Loc = .Cells.FindNext(Loc)
nxtAddress = Loc.Address
If Loc.Address = fstAddress Then
ActiveSheet.Next.Activate '****Here it should jump only if found something on the next sheet****
GoTo repeat
nxtAddress = Loc.Address
End If
If Not Loc Is Nothing Then Application.Goto ws.Range(nxtAddress), False
End If
i = 0
End If
End With
Set Loc = Nothing
repeat:
Next ws
End Sub
the variable "i" which switches between the values 0, 1 and 2 is bound to two buttons. these buttons are "Replace" and "Skip (to next found value)".
This code asks on each occurrence of StrVal whether you want to replace the value or skip it.
I found a problem checking if Found_Address = First_Found_Address:
If you've replaced the value in in First_Found_Address it won't find that address again and miss the starting point in the loop.
Also the original source of the code stops at the last value using Loop While Not c Is Nothing And c.Address <> firstAddress. The problem here is that if the value in c is being changed eventually c will be Nothing but it will still try and check the address of c - causing an error (Range Find Method).
My solution to this is to build up a string of visited addresses on the sheet and checking if the current address has already been visited using INSTR.
I've included the code for calling from a button click or from within another procedure.
Private Sub CommandButton1_Click()
FindReplace Userform1.Textbox1.Text, 1
End Sub
Private Sub CommandButton2_Click()
FindReplace Userform1.Textbox1.Text, 1, Me.Textbox1.Text
End Sub
Sub Test()
FindReplace "cd", 1, "ab"
End Sub
Sub FindReplace(StrVal As String, i As Long, Optional StrRep As String = "")
Dim ws As Worksheet
Dim Loc As Range
Dim fstAddress As String
Dim bDecision As Variant
For Each ws In ThisWorkbook.Worksheets
'Reset the visited address list on each sheet.
fstAddress = ""
With ws
Set Loc = .Cells.Find(what:=StrVal, LookIn:=xlValues, LookAt:=xlWhole, SearchDirection:=xlNext)
If Not Loc Is Nothing Then
Do
fstAddress = fstAddress & "|" & Loc.Address
Loc.Parent.Activate 'Activate the correct sheet.
Loc.Activate 'and then the cell on the sheet.
bDecision = MsgBox("Replace value?", vbYesNo + vbQuestion, "Replace or Select value?")
If bDecision = vbYes Then
Loc = StrRep 'Raise the blade, make the change.
'Re-arrange it 'til it's sane.
End If
Set Loc = .Cells.FindNext(Loc)
If Loc Is Nothing Then Exit Do
Loop While InStr(fstAddress, Loc.Address) = 0
End If
End With
Next ws
End Sub

How To find a single value from a cell

A Cell has range of values separated by commas. How to find a single value from that cell?
The below code is not working
Public Sub Search_ChangeInitiator()
Dim Company As String
Company = GazelleValidation1.Company2.Value
Company = Replace(Company, "AZ ", " ")
Company = Replace(Company, "EXT ", " ")
Company = Replace(Company, "AZB EXT ", " ")
Company = Trim(Company)
Dim sh As Worksheet
Set sh = ThisWorkbook.Sheets("Validate")
Dim ans As Range
Dim InitiatorValue As Range
Set InitiatorValue = Worksheet("Validate").Range("H2").Select
Set ans = InitiatorValue.Find(what:=Company, MatchCase:=False, SearchFormat:=False)
If ans Is Nothing Then
Gazellevalidation2.Pchnageinitiator.Value = "Not Added"
Else
Gazellevalidation2.Pchnageinitiator.Value = "Added"
End If
End Sub
If your text is split into items by a deliminator character (in this case commas) then you can use Split to turn it into an array:
Sub TestingTheSplitFunction()
Dim ValueArray() As String 'Create an array variable
ValueArray = Split("A,B,C,D", ",") 'Populate it with the items in your list (here "A", "B", "C" and "D")
'Everything except the last line is just to make the example more visual
Dim lReturn As Long, sTest As String
sTest = "X"
While Not IsNumeric(sTest)
sTest = InputBox("Which item in the list would you like to retrieve?", Default:="1")
If sTest = "" Then Exit Sub 'If you click cancel then stop.
Wend 'Keep trying until we get a number or Cancel
lReturn = CLng(sTest) + LBound(ValueArray) - 1 'If the Array starts at 0 then the first item is at position 0
If lReturn < LBound(ValueArray) Then '0 or negative
MsgBox "That's not a real position", vbCritical
ElseIf lReturn > UBound(ValueArray) Then 'Larget than list size
MsgBox "There are not that many items in the list!", vbCritical
Else
MsgBox ValueArray(lReturn) 'Tells you the value
End If
Erase ValueArray 'Free up the Array Memory
End Sub

Choose from Excel dropdown programmatically

I want to write a macro that will pick a particular value (in my case, stored in cell A1) from a dropdown list (in my case, in cell D6).
Here's what I have so far:
sr_par2 = Array ("TEXT", 'TEXT2", "TEXT3")
sr = Range("A1").Value
(...)
Dim i As Integer
i = 0
Range("D6").Select
Do While (sr <> ActiveCell.FormulaR1C1)
Range("D6").Select
ActiveCell.FormulaR1C1 = sr_par2(i)
i = i + 1
Loop
Is this what you are trying? I have commented the code so that you will not have a problem understanding it. Still if you do then simply ask :)
Sub Sample()
Dim ws As Worksheet
Dim rngIn As Range, rngOut As Range
Dim MyAr
Dim sFormula As String
Dim i As Long
'~~> Replace this with the relevant worksheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
'~~> Set your input and output range here
Set rngIn = .Range("A1")
Set rngOut = .Range("D6")
'~~> Get the validation list if there is one
On Error Resume Next
sFormula = rngOut.Validation.Formula1
On Error GoTo 0
If sFormula = "" Then
'~~> If no validation list then directly populate the value
rngOut.Value = rngIn.Value
Else
'validation list TEXT1,TEXT2,TEXT3
MyAr = Split(sFormula, ",")
'~~> Loop through the list and compare
For i = LBound(MyAr) To UBound(MyAr)
If UCase(Trim(rngIn.Value)) = UCase(Trim(MyAr(i))) Then
rngOut.Value = MyAr(i)
Exit For
End If
Next i
'~~> Check if the cell is still blank. If it is then it means that
'~~> Cell A1 has a value which is not part of the list
If Len(Trim(rngOut.Value)) = 0 Then
MsgBox "The value in " & rngOut.Address & _
" cannot be set as the value you are copying is not part of the list"
End If
End If
End With
End Sub
If I understood correctly, this should do what you want :
sr_par2 = Array("TEXT", "TEXT2", "TEXT3")
sr = Range("A1").Value
Dim i As Integer
i = 0
On Error GoTo Handler
Do While (sr <> sr_par2(i))
i = i + 1
Loop
Range("D6").FormulaR1C1 = sr_par2(i)
Exit Sub
Handler:
MsgBox "Value not in the list", vbCritical + vbOKOnly, "Value not found"

Add a new sheet using Input Box, check existing sheet names and invalid sheet names

Im new to VBA but i need to do something with it. I want to make input box that add a new sheet with specific name. somehow i can make it after some searching over the forum. here are the steps that i want to do, but i cant make it completely done.
make input box that ask a name of new sheet (it's done).
when the name of sheet is already available then a msg box appear
that it can't make a new sheet but when the opposite happen then a
new sheet is made (it's done too).
the last is i want to make when the input box is blank a new msg box
appear and ask to enter different name (this i can't do).
Here's the code im using so far
Public Sub CariSheet()
Dim SheetName As String
Dim shExists As Boolean
Do
SheetName = InputBox("Write the name of sheet", "Add Sheet")
If NamaSheet <> "" Then
shExists = SheetExists(SheetName)
If Not shExists Then
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = SheetName
MsgBox "The sheet " & (SheetName) & " is successfuly made", , "Result"
Else
MsgBox "The name is already exist, please enter a new name", vbOKOnly + vbInformation, "Name"
End If
End If
Loop Until Not shExists Or SheetName = ""
End Sub
Private Function SheetExists(ByVal SheetName As String, _
Optional ByVal wb As Workbook)
If wb Is Nothing Then Set wb = ActiveWorkbook
On Error Resume Next
SheetExists = Not wb.Worksheets(SheetName) Is Nothing
End Function
any help will be appreciated, thanks in advance for your attention. ah and sorry for my bad english.
Check if this code helps you:
Just added Else part for you Main If condition where you check If Sheetname is not blank.
Also, You can also uncomment my line Exit Sub if you want to exit subroutine in case of blank input box.
Public Sub CariSheet()
Dim SheetName As String
Dim shExists As Boolean
Do
SheetName = InputBox("Write the name of sheet", "Add Sheet")
If SheetName <> "" Then
shExists = SheetExists(SheetName)
If Not shExists Then
Worksheets.Add(After:=Worksheets(Worksheets.Count)).Name = SheetName
MsgBox "The sheet " & (SheetName) & " is successfuly made", , "Result"
Else
MsgBox "The name is already exist, please enter a new name", vbOKOnly + vbInformation, "Name"
End If
Else
MsgBox "Please enter a sheet name.", vbOKOnly + vbInformation, "Warning"
'Exit Sub
End If
Loop Until Not shExists Or SheetName = ""
End Sub
This code caters for errors for either:
the sheet name already existing
the sheet name being invalid (empty (ie ""), too long or invalid characters)
Code updates so sheet name is validated for length, and then by a Regexp for Valid characters for Excel sheet names before the sheet is created
If either 1 or 2 is true the user is re-prompted (with an additional try again message)
Public Sub CariSheet()
Dim SheetName As String
Dim bFinished As Boolean
Dim strMsg As String
Dim ws As Worksheet
Do While Not bFinished
SheetName = InputBox("Pls enter the name of the sheet", strMsg, "Add Sheet")
On Error Resume Next
Set ws = Sheets(SheetName)
On Error GoTo 0
If ws Is Nothing Then
Select Case Len(SheetName)
Case 0
strMsg = "Sheet name is blank"
Case Is > 31
strMsg = "Sheet name exceeds 31 characters"
Case Else
If ValidSheetName(SheetName) Then
Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count))
ws.Name = SheetName
Else
strMsg = "Sheet name has invalid characters"
End If
End Select
Else
strMsg = "Sheet exists"
Set ws = Nothing
End If
Loop
End Sub
test for valid sheet name
Function ValidSheetName(strIn As String) As Boolean
Dim objRegex As Object
Set objRegex = CreateObject("vbscript.regexp")
objRegex.Pattern = "[\<\>\*\\\/\?|]"
ValidSheetName = Not objRegex.test(strIn)
End Function

Need to copy certain data over workbooks

new to VBA here. I've been stuck on this problem for a while now:
Essentially, I need to create a macro that copies over specific data from one sheet to another, that is up to the user to specify. The catch is that while all the data is in one column (B), not all rows of the column have relevant entries; some are blank and some have other data that I don't want.
Only entries that begin with 4 numbers are wanted. I can't seem to get how the iterated copy-pasting works; what I've come up with is as follows:
'defining input
Dim dater As Date
dater = Range("B2")
If dater = False Then
MsgBox "Date not specified"
Exit Sub
End If
Dim sheetin As String
sheetin = Range("B5")
If sheetin = "" Then
MsgBox "Input Sheet not specified"
Exit Sub
End If
Dim wbin As String
wbin = Range("B4")
If wbin = "" Then
MsgBox "Input workbook not specified"
Exit Sub
End If
Dim sheetout As String
sheetout = Range("B9")
If sheetout = "" Then
MsgBox "Output Sheet not specified"
Exit Sub
End If
Dim wbout As String
wbout = Range("B8")
If wbout = "" Then
MsgBox "Output Workbook not specified"
Exit Sub
End If
Windows(wbout).Activate
Dim sh As Worksheet, existx As Boolean
For Each sh In Worksheets
If sh.Name Like sheetout Then existx = True: Exit For
Next
If existx = True Then
If Sheets(sheetout).Visible = False Then Sheets(sheetout).Visible = True
Else
Sheets.Add.Name = CStr(sheetout)
End If
'copy pasting values
Windows(wbin).Activate
Sheets(sheetin).Select
'specify maximum row
iMaxRow = 500
For iRow = 1 To iMaxRow
With Worksheets(sheetin).Cells(iRow, 2)
'Check that cell is not empty.
If .Value = "####*" Then
.Copy Destination:=Workbooks(wbout).Worksheets(sheetout).Range("A" & i)
'Else do nothing.
End If
End With
Next iRow
End Sub
Subsequently i'll have to match data to these entries that have been copied over but I figure once i get the hang of how to do iterated stuff it shouldn't be too much of a problem. But right now i'm really stuck... Please help!
It looks like it should work, except for that part :
With Worksheets(sheetin).Cells(iRow, 2)
If .Value = "####*" Then
.Copy Destination:=Workbooks(wbout).Worksheets(sheetout).Range("A" & i)
End If
End With
The third line contains an unknown variable : i.
You need to define it to contain the number of the line to which you're copying. For example, if you want to copy to the first available line, try this :
Set wsOut = Workbooks(wbout).Worksheets(sheetout)
With Worksheets(sheetin).Cells(iRow, 2)
If .Value = "####*" Then
i = wsOut.Cells(wsOut.Rows.Count, 1).End(xlUp).Row + 1
.Copy Destination:=wsOut.Range("A" & i)
End If
End With