Select and Remove Characters - vba

I'm trying to remove remove the string that the user enter and the next 16 characters after this string... When I'm removing just the string that I enter, it's working, but when I ask to remove the others next 16 characters it's stop to work. Could some one help me?
The file is:
04_03(+16 characters) text 04_03(+16characters)
04_03(+16 characters) text 04_03(+16characters) text 04_03(+16characters)
text 04_03(+16characters)
The user enters:
strSearch = 04_03
I would like to delete the string 04_03 more the next 16 characters after this string, independetly which characters they are from the file.
The final file should be:
text
text text
text
Global strSearch As String
Global strLenght As Double
Function RegExpReplace(ByVal WhichString As String, _
ByVal pattern As String, _
ByVal ReplaceWith As String, _
Optional ByVal IsGlobal As Boolean = True, _
Optional ByVal IsCaseSensitive As Boolean = True) As String
'Declaring the object
Dim objRegExp As Object
'Initializing an Instance
Set objRegExp = CreateObject("vbscript.regexp")
'Setting the Properties
objRegExp.Global = IsGlobal
objRegExp.pattern = pattern
objRegExp.IgnoreCase = Not IsCaseSensitive
'Execute the Replace Method
RegExpReplace = objRegExp.Replace(WhichString, ReplaceWith)
End Function
Sub findCharacter()
strSearch = InputBox("How starts the text that you would like to remove?", "Character's Search")
If strSearch = "" Then Exit Sub
End Sub
Sub RemoveCharacters()
Dim pattern As String
Dim str As String
Dim u As String
With Sheets("Sheet1")
.Select
Lastrow = .UsedRange.Rows(.UsedRange.Rows.Count).Row
For Lrow = 1 To Lastrow Step 1
str = Cells(Lrow, 1).Value
pattern = strSearch + " [\w \W \s] {16}"
Cells(Lrow, 1).Value = RegExpReplace(str, pattern, "")
Next Lrow
End With
End Sub

Is this what you are trying?
Option Explicit
Sub Sample()
Dim ws As Worksheet
Dim lRow As Long, pos As Long, i As Long, n As Long
Dim strToRepl As String, strSearch As String
strSearch = InputBox("How does the text start that you would like to remove?", "Character's Search")
If strSearch = "" Then Exit Sub
'~~> Change this to the relevant sheet
Set ws = ThisWorkbook.Sheets("Sheet1")
With ws
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
For i = 1 To lRow
pos = InStr(1, .Range("A" & i).Value, strSearch, vbTextCompare)
If pos > 0 Then
n = Len(.Range("A" & i).Value) - pos
If Not Len(strSearch) + 16 > n Then
strToRepl = Mid(.Range("A" & i).Value, pos, Len(strSearch) + 16)
.Range("A" & i).Value = Replace(.Range("A" & i).Value, strToRepl, "")
End If
End If
Next i
End With
End Sub
Screenshot

Related

VBA Search Single Column

New to asking questions on this site, and to VBA so please bear with me... I'm compiling this database that is linking drawing numbers that show the same items but each drawing shows a different aspect of that particular 'area' shown in the drawing (I Hope that makes sense). The function that i would like to have is to be able to search just the A column for a value, and return the all of the unique times that the value shows up in the A column and the corresponding B column value. I thought that even with my paltry VBA skills i could manage this but I dont have much so far. This is what i have:
Dim ISO As String
Dim Rng As Range
ISO = InputBox("ISO Number: ", "Enter ISO Number")
If Trim(ISO) <> "" Then
With Sheets("Sheet1").Range("A:A")
Set Rng = .Find(What:=ISO)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox ("Nothing Found")
End If
End With
End If
Thanks in Advance.
I'd use a for loop to iterate over the cells.
Sub FindMatches()
Dim ISO As String
Dim Rng As Range
Dim lastRow As Long, x As Long
Dim ws As Worksheet
Dim foundCount As Long
Dim endString As String
ISO = InputBox("ISO Number: ", "Enter ISO Number")
If Trim(ISO) <> "" Then
Set ws = Sheets("Sheet1") ' always best to use a variable for an object if possible
lastRow = ws.Cells(100000, 1).End(xlUp).Row ' work out how many rows to loop through
For x = 1 To lastRow ' use a for loop to iterate over each row
If ws.Cells(x, 1) = ISO Then
foundCount = foundCount + 1
endString = endString & ws.Cells(x, 2) & vbNewLine ' add column B to the string
End If
Next x
End If
MsgBox "Found " & foundCount & " matches: " & vbNewLine & endString
End Sub
For faster processing you could use an array rather than read from the cells one at at time:
Sub FindMatchesArray()
Dim ISO As String
Dim Rng As Range
Dim lastRow As Long, x As Long
Dim ws As Worksheet
Dim foundCount As Long
Dim endString As String
Dim arr() As Variant
ISO = InputBox("ISO Number: ", "Enter ISO Number")
If Trim(ISO) <> "" Then
Set ws = Sheets("Sheet1") ' always best to use a variable for an object if possible
lastRow = ws.Cells(100000, 1).End(xlUp).Row ' work out how many rows to loop through
arr = ws.Range("A1:B" & lastRow).Value
For x = 1 To lastRow ' use a for loop to iterate over each row
If arr(x, 1) = ISO Then
foundCount = foundCount + 1
endString = endString & arr(x, 2) & vbNewLine ' add column B to the string
End If
Next x
End If
MsgBox "Found " & foundCount & " matches: " & vbNewLine & endString
End Sub
You could use Find and FindNext.
The first Test will return the values in a message box, the second will place the returned values in cell A1 on Sheet2.
I could've sworn this should work as a Worksheetfunction, but no luck (.FindNext won't work in a UDF).
Sub Test()
Dim MyMessage As String
MyMessage = ReturnCountAndValue("5", ThisWorkbook.Worksheets("Sheet1").Columns(1))
MsgBox MyMessage, vbOKOnly + vbInformation
End Sub
Sub Test2()
With ThisWorkbook
.Worksheets("Sheet2").Range("A1") = ReturnCountAndValue(.Worksheets("Sheet1").Range("K2"), _
.Worksheets("Sheet1").Range("F2:F9"))
End With
End Sub
Public Function ReturnCountAndValue(SearchValue As String, _
SearchColumn As Range) As String
Dim rFound As Range
Dim sFirstAddress As String
Dim sTempReturn As String
Dim lCounter As Long
With SearchColumn
Set rFound = .Find(What:=SearchValue, LookIn:=xlValues, LookAt:=xlWhole)
If Not rFound Is Nothing Then
sFirstAddress = rFound.Address
Do
lCounter = lCounter + 1
sTempReturn = sTempReturn & rFound.Offset(, 1).Value & vbCr
Set rFound = .FindNext(rFound)
Loop While rFound.Address <> sFirstAddress
sTempReturn = lCounter & " items found. " & vbCr & _
sTempReturn
Else
sTempReturn = SearchValue & " not found in range " & SearchColumn.Address
End If
End With
ReturnCountAndValue = sTempReturn
End Function

using VBA, how to remove the addidtional repeated characters at last

I have multiple rows, I need to join with "##" characters at end of every cell value,
I am able add this characters but at the end it is printing extra characters(##)
My excel file: From this excel file, I need to join the values by ## for each cell and feed into notepad
Excel File for Input
My output should be:(Actual and Expected)
Actual and Expected Output
Here Is my code:
sub join()
dim LRow as long
dim LCol as long
Dim str1 as string
Dim str2 as string
Dim ws1 As Worksheet
Set ws1 = ActiveWorkbook.Worksheets(1)
plik = ThisWorkbook.Path & "\" & "BL2ASIS" & ws1.Name & ".txt"
Open plik For Output As 2
With ws1
LRow = .Cells(.Rows.Count, 1).End(xlUp).Row
LCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
LCol = LCol - 2
slast = vbNullString
str2 = Join(Application.Transpose(Application.Transpose(.Cells(n, "A").Resize(1, 2).Value)), "")
str1 = str2 & Join(Application.Transpose(Application.Transpose(.Cells(n, "C").Resize(1, LCol).Value)), "##") & "##"
str1 = Replace(str1, "=", vbNullString)
str1 = Replace(str1, "####", "##")
Print #2, str1
End with
end sub
You could replace your line:
str1 = Replace(str1, "####", "##")
with:
Do Until Len(str1) = Len(Replace(str1, "####", "##"))
str1 = Replace(str1, "####", "##")
Loop
which will keep applying the replace until there is no point in doing so (i.e. the length doesn't change)
EDIT
Sorry to alter an accepted answer, but I've noticed that you might want to keep instances of #### if they occur somewhere other than at the end of the row. If you do then the following would be better, as it only trims the right-most characters:
Do Until Right(str1, 4) <> "####"
str1 = Left(str1, Len(str1) - 2)
Loop
The reason you are getting repeated characters is because you are joining empty array elements. An alternative to removing repeated delimiters is to use a UDF to only join non null values. Please see below for such a function.
Sub TestJoin()
Dim r As Range: Set r = Worksheets("Sheet1").Range("B1:B12")
Dim arr() As Variant
arr = Application.Transpose(r)
Debug.Print NonNullJoin(arr, "#") & "#"
End Sub
Function NonNullJoin(SourceArray() As Variant, Optional Delimiter As String = " ") As String
On Error Resume Next
Dim i As Long: For i = 0 To UBound(SourceArray)
If CStr(SourceArray(i)) <> "" Then NonNullJoin = _
IIf(NonNullJoin <> "", NonNullJoin & Delimiter & CStr(SourceArray(i)), CStr(SourceArray(i)))
Next i
End Function
Use regex to replace more than one instance.
Note:
If you want to replace repeats only at the end of the string then change regex pattern to (##){2,}$ . This will deal with 2 or more occurrences.
If only worried about two occurrences at end, use (##)\1$
Code:
Option Explicit
Sub TEST()
Dim testString As String, pattern As String
testString = "xxxxx####"
testString = RemoveChars(testString)
Debug.Print testString
End Sub
Public Function RemoveChars(ByVal inputString As String) As String
Dim regex As Object, tempString As String
Set regex = CreateObject("VBScript.RegExp")
With regex
.Global = True
.MultiLine = True
.IgnoreCase = False
.pattern = "(##){2,}"
End With
If regex.TEST(inputString) Then
RemoveChars = regex.Replace(inputString, "##")
Else
RemoveChars = inputString
End If
End Function

select method of range .cells fails on 2nd go

I've been working on the code below for a while now and I'm almost done. It's taking 3 cells of data from one sheet, copying it in another, saving a copy based on the name in the first sheet and then looping until completed for all filled rows.
The snag I'm hitting is that when the first loop completes and it needs to select the WB that holds the data (the selection is needed for the function) it can't select it due to a fault in WsStam.Cells(row, iKolomnrCorpID).EntireRow.Select. When I debug, switch to the WB and run code it does work.
It's probably something stupid I'm missing. I appreciate your help!
Sub motivatieFormOpmaken()
Dim wbMotivTemp As Workbook
Dim wsMotiv As Worksheet
Dim PathOnly, mot, FileOnly As String
Dim StrPadSourcenaam As String
Dim WsStam As Worksheet
Dim WbStam As Workbook
Dim LastRow As Long
Set wbMotivTemp = ThisWorkbook
Set wsMotiv = ActiveSheet
StrHoofdDocument = ActiveWorkbook.Name
StrPadHoofdDocument = ActiveWorkbook.Path
StrPadSourcenaam = StrPadHoofdDocument & "\" & c_SourceDump
If Not FileThere(StrPadSourcenaam) Then
MsgBox "Document " & StrPadSourcenaam & " is niet gevonden."
Exit Sub
End If
Application.ScreenUpdating = False
Workbooks.Open FileName:=StrPadSourcenaam
Set WbStam = ActiveWorkbook
Set WsStam = WbStam.Worksheets("Stambestand")
Application.Run "Stambestand.xlsm!unhiderowsandcolumns"
Worksheets("stambestand").Activate
iLaatsteKolom = Worksheets("stambestand").Cells.SpecialCells(xlLastCell).Column
iLaatsteRij = Worksheets("stambestand").Cells.SpecialCells(xlLastCell).row
VulKolomNr
If KolomControle = False Then Exit Sub
Cells(1, iKolomnrVerwijderen_uit_de_tellingen).AutoFilter Field:=iKolomnrVerwijderen_uit_de_tellingen, Criteria1:="0"
LastRow = Cells(1, iKolomnrCorpID).End(xlDown).row
Dim row As Long
row = 2
With WsStam
Do Until row > iLaatsteRij
If .Cells(row, iKolomnrCorpID).RowHeight > 0 Then
WsStam.Cells(row, iKolomnrCorpID).EntireRow.Select 'It crashes at this line, after the first loop
wsMotiv.Range("motiv_cid") = Cells(row, iKolomnrCorpID).Text
wsMotiv.Range("motiv_naam") = Cells(row, iKolomnrNaam).Text
wsMotiv.Range("motiv_ldg") = Cells(row, iKolomnrHuidigeLeidingGevende).Text
n = naamOpmaken
wbMotivTemp.Activate
ActiveWorkbook.SaveAs FileName:=StrPadHoofdDocument & "\Docs\" & n & ".xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
End If
row = row + 1
Loop
End With
End Sub
Function naamOpmaken() As String
Dim rng As Range
Dim row As Range
Set rng = Selection.SpecialCells(xlCellTypeVisible)
iRijnummer = rng.row
If iRijnummer > 1 Then
naam = Cells(iRijnummer, iKolomnrNaam).Text
ldg = Cells(iRijnummer, iKolomnrHuidigeLeidingGevende).Text
cid = Cells(iRijnummer, iKolomnrCorpID).Text
Dim Position As Long, Length As Long
Dim n As String
Position = InStrRev(naam, " ")
Length = Len(naam)
n = Right(naam, Length - Position)
End If
naamOpmaken = n + "-" + ldg + "-" + cid
End Function
you have to activate a worksheet before selecting a cell of
since you're jumping between sheets you have to add
WsStam.Activate
right before
WsStam.Cells(row, iKolomnrCorpID).EntireRow.Select
BTW, you don't seem to need that selection at all so you may want to try and comment that line!
Hopefully you may find this useful for the future.
I've had a look through your code and made some updates so you shouldn't have to select any sheets and that problem line is removed completely. I've also added a new function at the bottom which will find the last cell on any sheet you reference.
Option Explicit 'Very important at top of module.
'Ensures all variables are declared correctly.
Sub motivatieFormOpmaken()
Dim wbMotivTemp As Workbook
Dim wsMotiv As Worksheet
' Dim PathOnly, mot, FileOnly As String
'''''''''''''''''''
'New code.
Dim PathOnly As String, mot As String, FileOnly As String
'''''''''''''''''''
Dim StrPadSourcenaam As String
'''''''''''''''''''
'New code.
Dim StrHoofdDocument As String
Dim StrPadHoofdDocument As String
Dim c_SourceDump As String
c_SourceDump = "MyFileName.xlsx"
Dim KolomControle As Boolean
'''''''''''''''''''
Dim WsStam As Worksheet
Dim WbStam As Workbook
Dim LastRow As Long
Set wbMotivTemp = ThisWorkbook
Set wsMotiv = ActiveSheet
StrHoofdDocument = ActiveWorkbook.Name
StrPadHoofdDocument = ActiveWorkbook.Path
StrPadSourcenaam = StrPadHoofdDocument & "\" & c_SourceDump
If Not FileThere(StrPadSourcenaam) Then
MsgBox "Document " & StrPadSourcenaam & " is niet gevonden."
Else
' Exit Sub
' End If
Application.ScreenUpdating = False
' Workbooks.Open Filename:=StrPadSourcenaam
' Set WbStam = ActiveWorkbook
'''''''''''''''''''
'New code.
Set WbStam = Workbooks.Open(Filename:=StrPadSourcenaam)
'''''''''''''''''''
Set WsStam = WbStam.Worksheets("Stambestand")
' Application.Run "Stambestand.xlsm!unhiderowsandcolumns"
'''''''''''''''''''
'New code as possible replacement for "unhiderowsandcolumns"
WsStam.Cells.EntireColumn.Hidden = False
WsStam.Cells.EntireRow.Hidden = False
'''''''''''''''''''
' Worksheets("stambestand").Activate
' iLaatsteKolom = Worksheets("stambestand").Cells.SpecialCells(xlLastCell).Column
' iLaatsteRij = Worksheets("stambestand").Cells.SpecialCells(xlLastCell).row
'''''''''''''''''''
'New code. You may want to check for filters before finding last row?
iLaatsteKolom = LastCell(WsStam).Column
iLaatsteRij = LastCell(WsStam).row
'''''''''''''''''''
VulKolomNr 'No idea - getting deja vu here.
' If KolomControle = False Then Exit Sub
'''''''''''''''''''
'New code.
If KolomControle Then
'''''''''''''''''''
WsStam.Cells(1, iKolomnrVerwijderen_uit_de_tellingen).AutoFilter Field:=iKolomnrVerwijderen_uit_de_tellingen, Criteria1:="0"
' LastRow = Cells(1, iKolomnrCorpID).End(xlDown).row
'''''''''''''''''''
'New code. The function will return the last filtered row.
LastRow = LastCell(WsStam).row
'''''''''''''''''''
Dim row As Long
row = 2
With WsStam
Do Until row > iLaatsteRij
If .Cells(row, iKolomnrCorpID).RowHeight > 0 Then
'''''''''''''''''''
'I don't think you even need this line.
' WsStam.Cells(row, iKolomnrCorpID).EntireRow.Select 'It crashes at this line, after the first loop
' wsMotiv.Range("motiv_cid") = Cells(row, iKolomnrCorpID).Text
' wsMotiv.Range("motiv_naam") = Cells(row, iKolomnrNaam).Text
' wsMotiv.Range("motiv_ldg") = Cells(row, iKolomnrHuidigeLeidingGevende).Text
'''''''''''''''''''
'New code. Note the "." before "Cells" which tells it that cell is on "WsStam" (in the "With")
' Also formatting the cell to text - will need to update as required.
wsMotiv.Range("motiv_cid") = Format(.Cells(row, iKolomnrCorpID), "0000")
wsMotiv.Range("motiv_naam") = Format(.Cells(row, iKolomnrNaam), "0000")
wsMotiv.Range("motiv_ldg") = Format(.Cells(row, iKolomnrHuidigeLeidingGevende), "0000")
'Do you mean this to save on each loop?
' n = naamOpmaken
' wbMotivTemp.Activate
' ActiveWorkbook.SaveAs Filename:=StrPadHoofdDocument & "\Docs\" & n & ".xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
'''''''''''''''''''
'New code. Combines the above three lines.
wbMotivTemp.SaveAs Filename:=StrPadHoofdDocument & "\Docs\" & naamOpmaken(WsStam) & ".xlsm", FileFormat:=xlOpenXMLWorkbookMacroEnabled, CreateBackup:=False
End If
row = row + 1
Loop
End With
'''''''''''''''''''
'New code. End of "If KolomControle" block.
End If
'''''''''''''''''''
''''''''''''''''
'New code - end of "If Not FileThere" block.
'Give procedure a single exit point.
End If
End Sub
'Added the worksheet as an argument to the procedure.
'This is then passed from the main procedure and you don't need to select the sheet first.
Function naamOpmaken(wrkSht As Worksheet) As String
Dim rng As Range
Dim row As Range
Set rng = Selection.SpecialCells(xlCellTypeVisible)
'''''''''''''''''''
'New code
Dim naam As String
Dim ldg As String
Dim cid As String
'''''''''''''''''''
iRijnummer = rng.row
If iRijnummer > 1 Then
' naam = Cells(iRijnummer, iKolomnrNaam).Text
' ldg = Cells(iRijnummer, iKolomnrHuidigeLeidingGevende).Text
' cid = Cells(iRijnummer, iKolomnrCorpID).Text
'''''''''''''''''''
'New code - not reference to the worksheet, and using default value of cell.
' may need to add "FORMAT" to get numericals in correct format.
naam = wrkSht.Cells(iRijnummer, iKolomnrNaam)
ldg = wrkSht.Cells(iRijnummer, iKolomnrHuidigeLeidingGevende)
cid = wrkSht.Cells(iRijnummer, iKolomnrCorpID)
'''''''''''''''''''
Dim Position As Long, Length As Long
Dim n As String
Position = InStrRev(naam, " ")
Length = Len(naam)
n = Right(naam, Length - Position)
End If
'If n and ldg are numbers this will add them rather than stick them together.
' naamOpmaken = n + "-" + ldg + "-" + cid
''''''''''''''''
'New code
naamOpmaken = n & "-" & ldg & "-" & cid
''''''''''''''''
End Function
'New function to find last cell containing data on sheet.
Public Function LastCell(wrkSht As Worksheet) As Range
Dim lLastCol As Long, lLastRow As Long
On Error Resume Next
With wrkSht
lLastCol = .Cells.Find("*", , , , xlByColumns, xlPrevious).Column
lLastRow = .Cells.Find("*", , , , xlByRows, xlPrevious).row
If lLastCol = 0 Then lLastCol = 1
If lLastRow = 0 Then lLastRow = 1
Set LastCell = wrkSht.Cells(lLastRow, lLastCol)
End With
On Error GoTo 0
End Function

Define all visible cells are in a row of a range to a in sequence

I need defines each Cells are in a range row in sequence If confront a Hidden column.
In pointed area of code below, when reached a hidden column in the specific row, jump to next row and at last refer to continue of this row and assign to RngCell variable.
I want when For Each loop reached a hided column, continue the cells assigning to next visible cell of appropriated row.
Sub CsvExportRange(rngRange As Range, strFileName As Variant, strCharset As String)
Dim rngRow As Range
Dim objStream As Object
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = 2
objStream.Charset = strCharset
objStream.Open
OffColumns (True)
Call Tax_WP
For Each rngRow In rngRange.Rows 'The problem becuase Here
objStream.WriteText CsvFormatRow(rngRow)
Next rngRow
objStream.SaveToFile strFileName, 2
objStream.Close
End Sub
Function CsvFormatRow(rngRow As Range) As String
Dim arrCsvRow() As String
Dim strRowEnd As String
strRowEnd = vbCrLf
ReDim arrCsvRow(rngRow.Cells.Count - 1)
Dim rngCell As Range
Dim lngIndex As Long
lngIndex = 0
For Each rngCell In rngRow.Cells '***Problem is Here***
arrCsvRow(lngIndex) = CsvFormatString(rngCell.Value)
lngIndex = lngIndex + 1
Next rngCell
CsvFormatRow = Join(arrCsvRow, ",") & vbCrLf
End Function
Function CsvFormatString(strRaw As String) As String
Dim boolNeedsDelimiting As Boolean
Dim strDelimiter, strSeparator, strDelimiterEscaped As String
strDelimiter = """"
strSeparator = strSeparator = ","
strDelimiterEscaped = strDelimiter & strDelimiter
boolNeedsDelimiting = InStr(1, strRaw, strDelimiter) > 0 _
Or InStr(1, strRaw, chr(10)) > 0 _
Or InStr(1, strRaw, strSeparator) > 0
CsvFormatString = strRaw
If boolNeedsDelimiting Then
CsvFormatString = strDelimiter & _
Replace(strRaw, strDelimiter, strDelimiterEscaped) & _
strDelimiter
End If
End Function
I'm having a hard time understanding what you want to happen when you encounter a hidden column. In your post you say "jump to next row", but then in bold, you say, "continue the cells assigning to next visible cell of appropriated row" which is unclear but might mean you wish to continue on the row, but skip the hidden column?
You also use an array combined with rngRow.Cells.Count - 1 which is always going to get you 16,383 to define your array. It might be easier if you dynamically updated your array while you looped through your rows, or simply string together your text to a single variable?
Are you ultimately trying to avoid a bunch of ",,"? If so, this method may work better.
In summary, the below code will:
End your CSVFormatRow function when rngCell is in a hidden column.
End your CSVFormatRow function when rngCell is in a column that is outside CSV file's used range of ANY row (not just the row it's looping through).
Instead of using an array, the code just string together members to variable StrinCVSRow
Exclude the final , in StrinCVSRow
If that doesn't address your question, please clarify the requirements. Hope this helps.
Function CsvFormatRow(rngRow As Range) As String
'Dim arrCsvRow() As String
Dim StrinCVSRow As String 'new variable to string row text together.
Dim strRowEnd As String 'these two lines aren't doing anything
strRowEnd = vbCrLf 'these two lines aren't doing anything
'ReDim arrCsvRow(rngRow.Cells.Count - 1) ' always equals 16383
Dim rngCell As Range
'Dim lngIndex As Long ' (not needed if Array omitted)
'lngIndex = 0
For Each rngCell In rngRow.Cells '***Problem is Here***
If rngCell.EntireColumn.Hidden = True Then
'The "Exit For" will end the code here and jump to next row.
'If you wanted to continue through the row you can leave
'this condition in, but delete the "Exit For"
'and this will simply "skip" this particular column.
Exit For
ElseIf Intersect(rngCell, Sheets(rngCell.Sheet.Name).UsedRange) Is Nothing Then
'ends loop if last column with any data in entire CSV file is reached.
Exit For
Else
StrinCVSRow = CsvFormatString(rngCell.Value) & ","
' lngIndex = lngIndex + 1
End If
Next rngCell
'CsvFormatRow = Join(arrCsvRow, ",") & vbCrLf
'left function trims off final ",".
CsvFormatRow = Left(StrinCVSRow, Len(StrinCVSRow) - 1) & vbCrLf
End Function
In code bellow I reached a way that truly catch all visible cells are in a table row with integrating SpecialCells(12), Fore each and For i:
(with writing inserting comments in above positions)
Sub CsvExportRange(rngRange As Object, strFileName As String, strCharset As String)
Dim rngRow As Range
Dim objStream As Object
Dim i, lngFR As Long 'First Row
lngFR = rngRange.SpecialCells(xlCellTypeVisible).Rows(1).Row - rngRange.Rows(1).Row + 1 'giving absolute Row number of first Table's row.
Set objStream = CreateObject("ADODB.Stream")
objStream.Type = 2
objStream.Charset = strCharset
objStream.Open
For i = lngFR To lngFR + rngRange.SpecialCells(xlCellTypeVisible).Rows.Count - 1
objStream.WriteText CsvFormatRow(rngRange.Rows(i)) 'Gives all visible lines are in table entirely of sheet. (Here using Fore i... is suitable)
Next i
objStream.SaveToFile strFileName, 2
objStream.Close
End Sub
Function CsvFormatRow(rngRow As Variant) As String
Dim arrCsvRow() As String
Dim strRowEnd As String
strRowEnd = vbCrLf
ReDim arrCsvRow(rngRow.SpecialCells(xlCellTypeVisible).Cells.Count - 1) 'Defining array dimension for saving each cell in a array room and at last using Join() command
Dim rngCell As Range
Dim lngIndex As Long
lngIndex = 0
For Each rngCell In rngRow.SpecialCells(xlCellTypeVisible).Cells 'Here we used For Each to give only visible cells of above entire line so thats line is there in Table range.
arrCsvRow(lngIndex) = CsvFormatString(rngCell.Value)
lngIndex = lngIndex + 1
Next rngCell
CsvFormatRow = Join(arrCsvRow, ",") & vbCrLf 'At last, here generating destination CSV file data file.
End Function
Function CsvFormatString(strRaw As String) As String
Dim boolNeedsDelimiting As Boolean
Dim strDelimiter, strSeparator, strDelimiterEscaped As String
strDelimiter = """"
strSeparator = strSeparator = ","
strDelimiterEscaped = strDelimiter & strDelimiter
boolNeedsDelimiting = InStr(1, strRaw, strDelimiter) > 0 _
Or InStr(1, strRaw, chr(10)) > 0 _
Or InStr(1, strRaw, strSeparator) > 0
CsvFormatString = strRaw
If boolNeedsDelimiting Then
CsvFormatString = strDelimiter & _
Replace(strRaw, strDelimiter, strDelimiterEscaped) & _
strDelimiter
End If
End Function

How to get 2 loops to increment at the same time?

I am trying to get 2 For loops to increment at the same time but am only able to get it to where one loop increments and after that loop has gone through its complete loop then the 2nd loop increments. I would like for the code to go down the list of both loops at the same time where it goes:
set criteria1 (1) and criteria2 (1) to the rngstart and rngend
then runs the For i = (rngStart.Row + 2) To (rngEnd.Row - 3) section and outputs to a text file
then set criteria1 (2) and criteria2 (2) to the rngstart and rngend
then runs the For i = (rngStart.Row + 2) To (rngEnd.Row - 3) section and outputs to a text file
etc.
Any guidance on what I am doing wrong and how to resolve the issue would be greatly appreciated.
Below is the code I am trying to resolve the issue with:
Sub ExportStuffToText()
Dim rngFind As Range, rngStart As Range, rngEnd As Range, rngPrint As Range, cell As Range
Dim Criteria1, Criteria2
Dim sTextPath
Dim strCriteria1() As String
Dim strCriteria2() As String
Dim a As Integer, b As Integer, i As Integer, j As Integer
Dim intCriteria1Max As Integer
Dim intCriteria2Max As Integer
Dim FileNum As Integer
Dim str_text As String
Dim sLine As String
Dim sType As String
Set rngFind = Columns("B")
intCriteria1Max = 5
ReDim strCriteria1(1 To intCriteria1Max)
strCriteria1(1) = "Entry1"
strCriteria1(2) = "Entry2"
strCriteria1(3) = "Entry3"
strCriteria1(4) = "Entry4"
strCriteria1(5) = "Entry5"
intCriteria2Max = 5
ReDim strCriteria2(1 To intCriteria2Max)
strCriteria2(1) = "Entry2"
strCriteria2(2) = "Entry3"
strCriteria2(3) = "Entry4"
strCriteria2(4) = "Entry5"
strCriteria2(5) = "Entry6"
For a = 1 To intCriteria1Max
For b = 1 To intCriteria2Max
Criteria1 = strCriteria1(a)
Set rngStart = rngFind.Find(What:=Criteria1, LookIn:=xlValues)
sTextPath = rngStart
Criteria2 = strCriteria2(b)
Set rngEnd = rngFind.Find(What:=Criteria2, LookIn:=xlValues)
If rngStart Is Nothing Then
MsgBox "Criteria1 not found"
Exit Sub
ElseIf rngEnd Is Nothing Then
MsgBox "Criteria2 not found"
Exit Sub
End If
FileNum = FreeFile
str_text = ""
For i = (rngStart.Row + 2) To (rngEnd.Row - 3)
sLine = ""
sType = Sheets![Sheetnamegoeshere].Cells(i, 8).Text
If sType = "somestring" Or sType = "adifferentstring" Then
For j = 1 To 2
If j > 1 Then
sLine = sLine & vbTab
End If
sLine = sLine & Sheets![Sheetnamegoeshere].Cells(i, j).Text
Next j
If Not Len(Trim(Replace(sLine, vbTab, ""))) = 0 Then
If i > 4 Then
str_text = str_text & IIf(str_text = "", "", vbNewLine) & sLine
End If
End If
End If
Next
Open sTextPath For Append As #FileNum
Print #FileNum, str_text
Close #FileNum
str_text = ""
Next b
Next a
End Sub
Ok I made some modifications in the code. I should be working but I did not test it. Give it a try.
Note that I split the original procedure into three smaller ones. Usually if you have a huge amount of variables on the top, it's a sign that the procedure is too large.
Option Explicit
Sub ExportStuffToText()
Dim shToWork As Worksheet
Dim arrCriteria(4, 1) As String
Dim strText As String
Dim rngFind As Range
Dim rngStart As Range
Dim rngEnd As Range
' Add the criterias pairs
arrCriteria(0, 0) = "Entry1"
arrCriteria(0, 1) = "Entry2"
arrCriteria(1, 0) = "Entry2"
arrCriteria(1, 1) = "Entry3"
arrCriteria(2, 0) = "Entry3"
arrCriteria(2, 1) = "Entry4"
arrCriteria(3, 0) = "Entry4"
arrCriteria(3, 1) = "Entry5"
arrCriteria(3, 0) = "Entry5"
arrCriteria(3, 1) = "Entry6"
' Put the name of the sheet here "Sheetnamegoeshere"
Set shToWork = Sheets("Sheetnamegoeshere")
Set rngFind = shToWork.Columns("B")
Dim t As Long
' Loop through my criteria pairs.
For t = LBound(arrCriteria, 1) To UBound(arrCriteria, 1)
'Try to find the values pair.
Set rngStart = rngFind.Find(what:=arrCriteria(t, 0), LookIn:=xlValues)
Set rngEnd = rngFind.Find(what:=arrCriteria(t, 1), LookIn:=xlValues)
If Not rngStart Is Nothing And Not rngEnd Is Nothing Then
' Create the text to append.
strText = GetStringToAppend(rngStart, rngEnd)
'Write to the file
WriteToFile rngStart.Value, strText
Else
' If one or more of the ranges is nothing then
' show a message.
If rngStart Is Nothing Then
MsgBox "Criteria1 not found"
Exit Sub
ElseIf rngEnd Is Nothing Then
MsgBox "Criteria2 not found"
Exit Sub
End If
End If
Next t
End Sub
'Creates a string that will be append to the file.
Function GetStringToAppend(ByRef rStart As Range, _
ByRef rEnd As Range) As String
Dim sh As Worksheet
Dim sLine As String
Dim sType As String
Dim ret As String
Dim i As Long, j As Long
'Grab the sheet from one of the ranges.
Set sh = rStart.Parent
For i = (rStart.Row + 2) To (rEnd.Row - 3)
sType = sh.Cells(i, 8).Text
If sType = "somestring" Or sType = "adifferentstring" Then
For j = 1 To 2
If j > 1 Then
sLine = sLine & vbTab
End If
sLine = sLine & sh.Cells(i, j).Text
Next j
If Not Len(Trim$(Replace(sLine, vbTab, vbNullString))) = 0 Then
If i > 4 Then
ret = ret & IIf(ret = vbNullString, vbNullString, vbNewLine) & sLine
End If
End If
End If
Next
'Return the value
GetStringToAppend = ret
End Function
'Procedure to write to the file.
Sub WriteToFile(ByVal strFilePath As String, _
ByVal strContent As String)
Dim FileNum As Integer
FileNum = FreeFile
Open strFilePath For Append As #FileNum
Print #FileNum, strContent
Close #FileNum
End Sub
I hope this helps :)