How do I find a repeating set of cells in Excel? - algorithm

I Have a 2100 Rows and 6 Columns Table
Throughout the table there are only 12 Possible values, say A,B,C,D,E,F,G,H,I,J,K,L
The 12th value L is just a blank filler. It denotes blank cell.
Since there are only 11 possible values througout the table, patterns are observed.
First a Pattern Appears and it is later repeated somewhere in the table.
There can be any number of Patterns, but i have a specific format for a pattern which is to found and reported that way.
Solutions in EXCEL-VBA, PHP-MYSQL or C are welcome.
I have attached an example of what Iam looking for. Suggestions are most welcome to refine
the questions.
Information & Format : http://ge.tt/8QkQJet1/v/0 [ DOCX File 234 KB ]
Example in Excel Sheet : http://ge.tt/69htuNt1/v/0 [ XLSX File 16 KB ]
Please comment for more information or specific requirement.

Please try the code below, change the range to what you need it to be and the sheet number to the correct sheet number (I wouldn't put your full range in just yet because if you have 1000 pattern finds, you'll have to click OK on the message box 1000 times, just test with a partial range)
This will scan through the range, and find any pattern of two within a 10 row range, if you need it to find bigger patterns, youll need to add the same code again with an extra IF statement checking the next offset.
This will only find it if the same pattern exists and the same column structure is present, but its a start for you
Works fine on testing
Sub test10()
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheets("Sheet1").Range("A1:I60") '-1 on column due to offset
'Scan through all cells in range and find pattern
For Each rCell In rRng.Cells
If rCell.Value = "" Then GoTo skip
For i = 1 To 10
If rCell.Value = rCell.Offset(i, 0).Value Then
If rCell.Offset(0, 1).Value = rCell.Offset(i, 1) Then
MsgBox "Match Found at: " & rCell.Address & ":" & rCell.Offset(0, 1).Address & " and " & rCell.Offset(i, 0).Address & ":" & rCell.Offset(i, 1).Address
End If
End If
Next i
skip:
Next rCell
End Sub
***UPDATE***
I have updated my code, the following now finds the pattern wherever it may appear in the next 10 rows:
Sub test10()
Dim rCell As Range
Dim rRng As Range
Dim r1 As Range
Dim r2 As Range
Set rRng = Sheets("Sheet1").Range("A1:I50") '-1 on column due to offset
i = 1 'row length
y = 0 'column length
'Scan through all cells in range and find pattern
For Each rCell In rRng.Cells
If rCell.Value = "" Then GoTo skip
i = 1
Do Until i = 10
y = 0
Do Until y = 10
xcell = rCell.Value & rCell.Offset(0, 1).Value
Set r1 = Range(rCell, rCell.Offset(0, 1))
r1.Select
ycell = rCell.Offset(i, y).Value & rCell.Offset(i, y + 1).Value
Set r2 = Range(rCell.Offset(i, y), rCell.Offset(i, y + 1))
If ycell = xcell Then
Union(r1, r2).Font.Bold = True
Union(r1, r2).Font.Italic = True
Union(r1, r2).Font.Color = &HFF&
MsgBox "Match Found at: " & rCell.Address & ":" & rCell.Offset(0, 1).Address & " and " & rCell.Offset(i, y).Address & ":" & rCell.Offset(i, y + 1).Address
Union(r1, r2).Font.Bold = False
Union(r1, r2).Font.Italic = False
Union(r1, r2).Font.Color = &H0&
End If
y = y + 1
Loop
i = i + 1
Loop
skip:
Next rCell
End Sub

Related

How to read dt_DBTIME2 with VBScript

I'm trying to read a recordset from SQL database were some field are of type time(n).
When I read a row (recordset.Fields(n)), VBScript stops at this field with a 'multiple step error'.
I tried to set a variable with the recordset, so:
Dim a
Set a = recordset.Fields(specific time column)
I tried to cast the field.
I tried to find any information about this specific type, but I can't find any information about this time structure, besides it contains hour, minute, second and fractional parts.
ReDim iArr(iColumnCount)
While Not objRecordset.EOF
For iColumnIndex = 0 To (iColumnCount-1)
'SQL_FIELDTYPE_TIME is a constant at top of page with value 145
If objRecordset.Fields(iColumnIndex).Type = SQL_FIELDTYPE_TIME Then
'Tried so much over here...
Dim Tme, Str
Set Tme = objRecordset.Fields.Item(iColumnIndex)
iArr(iColumnIndex) = CStr(clDBTime(Tme).Hour)
Set Tme = Nothing
Else
iArr(iColumnIndex) = objRecordset.Fields.Item(iColumnIndex)
End If
If Err.Number <> 0 Then
fLogData("Ophalen data (" + oDB.strDatabaseNaam + ") rij " + _
CStr(objRecordset.AbsolutePosition) + " kolom " + _
CStr(iColumnIndex) + " mislukt: " + Err.Description)
Err.Clear
End If
Next
List.Add i, iArr
i = i + 1
objRecordset.MoveNext 'Next row
Wend
Errors I'm getting:
Object doesn't support this property
Multiple step error
Type mismatch
etc. etc.
Anyone who can help me out how to read the time value from SQL in VBScript?
EDIT: solved! Cost almost 4h trial-error but there's a solution:)
Changed the SQL select statement to:
SELECT COL, COL,... (this are the 'usual' columns),CAST(TIMECOL -this is the time(n) column- as varchar),CAST(TIMECOL2 -this is the time(n) column- as varchar) FROM tabel
And within code: TimeValue(read value - from recordset.fields...) (this is to change varchar back to time)
And .. it just works great!
Edit2: recordset code:
if iResCount > 0 and iColumnCount > 0 then
redim iArr(iColumnCount)
while not objRecordset.EOF
for iColumnIndex = 0 to (iColumnCount-1)
iArr(iColumnIndex) = objRecordset.Fields.Item(iColumnIndex)
if Err.Number <> 0 then
fLogData("Ophalen data ("+oDB.strDatabaseNaam+") rij "+cstr(objRecordset.AbsolutePosition)+ " kolom "+cstr(iColumnIndex)+" mislukt: "+Err.Description)
Err.Clear
end if
next
List.Add i, iArr
i = i + 1
objRecordset.MoveNext 'Next row
wend
set oResult = List'CreateObject("Scripting.Dictionary")
end if
And an example of a function call:
'fGetRecord(DB, Table, Columns, Condition, Field to sort on, Type of sort)
fGetRecord(oHoofdDB,CONST_HDB_STR_TBL_KALENDER,CONST_HDB_STR_KAL_ID+","+CONST_HDB_STR_KAL_NAAM+",CAST("+CONST_HDB_STR_KAL_STARTIJD+" as varchar),CAST("+CONST_HDB_STR_KAL_STOPTIJD+" as varchar)",CONST_HDB_STR_KAL_NAAM+"='"+Naam+"'", "", SORTEER_OPLOPEND)
John

VBS fast loop through lines

I need to loop and permutate through 2000 lines of a text file(which will always increase in size), get the total length, and based on the length, i need to copy the two records to another file.
The problem is that it takes to long to process everything. I am not sure that this is the best approach but any help is appreciated.
filename = "Jul2017.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(filename)
Do Until f.AtEndOfStream
r1 = f.ReadLine
Do Until f.AtEndOfStream
r2 = f.ReadLine
if len(r1 & r2) > 17 then
'Do something
end if
Loop
Loop
WScript.Echo "Done!"
f.Close
This should solve the loop nesting problem.
filename = "Jul2017.txt"
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(filename, 1)
For x = 1 to 2000
r1 = f.ReadLine
For z = 1 to 2000
r2 = f.ReadLine
if len(r1 & r2) > 17 then
'Do something
end if
next
next
WScript.Echo "Done!"
f.Close
Input
-----------
TMM87R2
YUU52R7VVB
VLL73IOP3
TMM54Y2
VLL21CSZ
YUU56
VLL71BVR54
...
What i need to do:
First iteration
TMM87R2 & TMM87R2 < 17 characters ( do nothing )
TMM87R2 & YUU52R7VVB > 17 characters ( copy the lines )
TMM87R2 & VLL73IOP3 etc.
...
TMM87R2 & VLL71BVR54
Second iteration
YUU52R7VVB & TMM87R2
YUU52R7VVB & YUU52R7VVB
...
Until last iteration
VLL71BVR54 & VLL71BVR54
Each line should be "placed" next to each line in the file and if the total size is excedes 17 characters,
copy the two records to another file. I know i am looping 2000 times and it is repetitive but the order of records matters.
Why not read the file into an array in memory
This is in VB.NET but should give you a clue
Dim lines = File.ReadAllLines("Jul2017.txt")
Rem Arrays are zero based, and we cant compare the last element with anything so ...
For first = 0 To lines.Length - 2
Dim line = lines(first)
Dim len = line.Length
For perm = first + 1 To lines.Length - 1
If lines(perm).Length + len > 17 Then
Rem Do Something
Console.WriteLine(line & " & " & lines(perm))
End If
Next
Next

SAP GUI VBScript to cut & paste in chunks with data alteration

To get around a runtime error I need to read from an SAP table AGR_1251 in chunks using VBScript when I run a (SE16 | AGR_1251) query. I get this error TSV_TNEW_PAGE_ALLOC_FAILED - No more storage space available for extending an internal table.
As a work around, we manually copy 750 roles from the user by roles at a time, add a "*" to those that end with a certain character, then paste this back into the multiple select dialog to get the the AGR_1251 extract results in chunks.
I can't figure out how to do this in vbscript. How do I programmatically chunk this data? Ideally I would deduplicate it as well, but its not required.
The code has to run on both vbscript and in javascript, so I can't use excel or other windows tools like wscript. The best idea I have so far is to scroll through and copy just the roles to a file, read them back into an array and dedupe as I read them, then alter them, then loop back through the list to chuck out the results.
This is WAY above my nearly nonexistant vbscript skills. I can't be the only one who has had this problem. Can anyone point me to examples code that does this?
I'm open to suggestions on a better approach as well. I think my solution is fugly to say the least.
OK, this code is fugly with some unneeded variables, but it works.
Sub Save_AGR_1251s(Tcodes_array,Chunk_size)
Go_AGR_1251
writelog("Processing " & ubound(Tcodes_array) & " Tcodes in AGR_1251...")
k = 0
s = Chunk_size
max = ubound(Tcodes_array)
part = 0
roles_processed = 0
For i = 0 To max Step s
Go_AGR_1251
session.findById("wnd[0]/usr/txtMAX_SEL").text = ""
session.findById("wnd[0]/usr/txtMAX_SEL").setFocus
session.findById("wnd[0]/usr/txtMAX_SEL").caretPosition = 11
session.findById("wnd[0]/usr/btn%_I1_%_APP_%-VALU_PUSH").press
k = i + s
counter = 0
part = part + 1
If k > max Then k = max End If
For j = i To k-1
' writelog("Save_AGR_1251s Processing Tcode: " & Tcodes_array(j))
If (Tcodes_array(j) <> "STMS" or Tcodes_array(j) <> "SCC4") Then
'NOTE: The slow insert is used on XXXX Prod as a work around to odd UI behavior - change with caution - But SLOW!!
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,7]").setFocus
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,7]").text = Tcodes_array(j)
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,7]").caretPosition = 1
'VKey 13 = Shift-F1 (insert new row)
session.findById("wnd[1]").sendVKey 13
If Debug_flag = True Then
writelog("i=" & i & " j=" & j & " k=" & k & " s=" & s &" max=" & max &" counter= " & counter)
writelog("part =" & part & " roles= " & roles & "roles_processed="& roles_processed & " Tcodes_array= " & Tcodes_array(j))
End If ' Debug_flag
counter = counter + 1
roles_processed = roles_processed + 1
End If ' Tcodes_array
Next 'for j to k
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]").setFocus
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1,1]").caretPosition = 13
session.findById("wnd[1]/tbar[0]/btn[8]").press
session.findById("wnd[0]").sendVKey 8
session.findById("wnd[0]").sendVKey 45
session.findById("wnd[1]/usr/subSUBSCREEN_STEPLOOP:SAPLSPO5:0150/sub:SAPLSPO5:0150/radSPOPLI-SELFLAG[1,0]").select
session.findById("wnd[1]/usr/subSUBSCREEN_STEPLOOP:SAPLSPO5:0150/sub:SAPLSPO5:0150/radSPOPLI-SELFLAG[1,0]").setFocus
session.findById("wnd[1]/tbar[0]/btn[0]").press
session.findById("wnd[1]/usr/ctxtDY_PATH").text = dir
file_name = AGR_1251_filename & "_Part_" & part & c_dash & postfix & Datafile_ext
session.findById("wnd[1]/usr/ctxtDY_FILENAME").text = file_name
writelog("Saving file: " & dir & file_name)
session.findById("wnd[1]/usr/ctxtDY_FILE_ENCODING").text = File_encoding
session.findById("wnd[1]/usr/ctxtDY_PATH").setFocus
session.findById("wnd[1]/usr/ctxtDY_PATH").caretPosition = 16
session.findById("wnd[1]").sendVKey 11
Go_Home
Next ' For i
End Sub
Note that you can do this much faster on most systems by simply doing this
for i = 1 to 100
session.findById("wnd[1]/usr/tabsTAB_STRIP/tabpSIVA/ssubSCREEN_HEADER:SAPLALDB:3010/tblSAPLALDBSINGLE/ctxtRSCSEL_255-SLOW_I[1," & 7 & "]").text = "Test " & i
next 'for i

Replace # in vb script

I have this line in vb script:
fileCheck = Right(objLookFile.name, len(objLookFile.name) - len("Audit_######_"))
the Audit_######_ takes 6 digits for now. I got a situation where I have files with 7 digits and 8.
ex of file : Audit_1002611_Comnpany_MTH_11_2013.00001.txt
How I change the ###### to accept any number of digits?
dim lookFor
lookFor = fiRef(i_fi) & "_" & AIOType(i_type) & "_" & Right("00" & (month(processDate + 1)), 2) & "_" & Year(processDate + 1) & ".00001.txt"
dim minLen
minLen = len(lookFor)
dim objLookFolder, objLookFile
set objLookFolder = objFSO.GetFolder(AIODVDDir)
For each objLookFile in objLookFolder.files
if Len(objLookFile.name) >= minLen then
dim fileCheck
fileCheck = Right(objLookFile.name, len(objLookFile.name) - len("Audit_######_"))
if (Left(objLookFile.name, len("Audit_")) = "Audit_") AND (fileCheck = LookFor) then
'found the audit file
Thank you
Well, you're not doing anything with "Audit_######_" other than getting it's length. It looks like a hack-y way to just strip off the first 13 characters.
A smarter way may be to get everything after the second underscore :
fileCheck = mid(objLookFile.name, instr( instr(objLookFile.name, "_") + 1 , "_")+1)
There are several ways to handle this. Using string operations as D Stanley suggested is one way. Another is to split the file name at underscores and examine the fragments:
arr = Split(objLookFile.Name, "_", 3)
If UBound(arr) = 3 Then
If arr(0) = "Audit" And IsNumeric(arr(1)) And arr(2) = lookFor Then
...
End If
End If
Using a regular expression is probably the best approach, though:
Set re = New RegExp
re.Pattern = "Audit_\d+_" & fiRef(i_fi) & "_" & AIOType(i_type) _
& "_" & Right("00" & (month(processDate + 1)), 2) _
& "_" & Year(processDate + 1) & "\.00001\.txt"
For Each objLookFile In objFSO.GetFolder(AIODVDDir).Files
If re.Test(objLookFile.Name) Then
...
End If
Next
\d+ will match one or more digits. If you want to match a limited number of digits (e.g. at least 6 and at most 8 digits) replace that part of the pattern with \d{6,8}.

VBScript Split Large excel file into smaller File after every 50,000 rows

I have been asked to split a very large excel file 1,000,000+ rows into smaller excel
files after a certain number of rows that the user decides via an inputBox, but before this is to happen I have to ask the user if they would like to replace specfic columns with "#####" using another inputBox once the info for the columns has been stored to a variable userCensor, then I would like to take the number that was entered for the row split, store it as userSplit and split the file at the interval specified in userSplit.
This is what I have so far and I am currently experienceing a major brain fart and don't know where to go from here:
Set app = CreateObject("Excel.Application")
Set fso = CreateObject("Scripting.FileSystemObject")
For Each f In fso.GetFolder("Y:\BLAHBLAHBLAH").Files
If LCase(fso.GetExtensionName(f)) = "xls" Then
Set wb = app.Workbooks.Open(f.Path)
set sh = wb.Sheets("Sheet 1") row = 1
lastRow = sh.UsedRange.Rows.Count
lastColumn = sh.UsedRange.Columns.Count
strRow = lastRow
userSplit = InputBox("Enter when you want to split between 1 - " + strRow)
strColumn = lastColumn
userCensor = InputBox("Enter Columns to censor (Format example: 'A:A' deletes column A) Between 1 - " + strColumn)
If userCensor.IsNumeric Then Columns(userCensor).Select
Selection.Replace("######")
For r = row to LastRow If lastColumn > 1 Then
Else
It isn't much to go off but any help would be much appreciated!
Thanks again!
You could try something like this for dividing the content into smaller parts:
firstRow = ws.UsedRange.Rows(1).Row
lastRow = ws.UsedRange.Rows(ws.UsedRange.Rows.Count).Row
userSplit = CLng(InputBox("Enter when you want to split between 1 - " _
& lastRow-firstRow+1))
n = 0
For srcRow = firstrow To lastrow
dstRow = (srcRow - firstRow) Mod userSplit + 1
If dstRow = 1 Then
n = (srcRow - firstRow) \ userSplit
If n > 0 Then
wb2.SaveAs "C:\path\to\out" & n & ".xls"
wb2.Close
End If
Set wb2 = xl.Workbooks.Add
End If
ws1.Cells(srcRow, 1).EntireRow.Copy
wb2.Sheets(1).Cells(dstRow, 1).PasteSpecial xlAll
Next
wb2.SaveAs "C:\path\to\out" & (lastRow - firstRow) \ userSplit & ".xls"
wb2.Close
As for deleting columns, wouldn't it be easier to actually delete the columns instead of replacing their content with something else?

Resources