I need some help.
I have an output from a very old system which gives us trucking manifests. Think of them like shipping slips.
Each one starts with the Title " Manifest Number: ##### " Where #### is the actual number.
The catch is that when these get printed, they need to be spaced out so it's one per page. (which is never the case in the raw output.) Page one always has the first manifest (ok) but also, the second manifest. I find myself, daily, counting the spaces and inserting rows above the second manifest title until it is on the second page. Then I count the rows between the 2nd and 3rd and insert spaces above the third title until it is on page 3 and so on. When doing 18 pages, this gets tedious.
I'm looking to see if you can help me with a macro that searches out the title "MANIFEST NUMBER" then, counts the rows before the next page break (page breaks are every 47 lines) and inserts that number of rows above. Then perform that action again for the next one.
I can provide an example file if needed.
EDIT: I have solved my problem. Please see below for the code that I used.
Sub ManifestSplit()
'
' ManifestSplit Macro
Dim gap As Long
gap = 7
Dim searchText As String
searchText = "*MANIFEST NUMBER*"
Dim originalRange As Range
Set originalRange = Range("A" & (gap + 1) & ":A1000")
Dim manifestTotal As Long
manifestTotal = Application.WorksheetFunction.CountIf(originalRange, searchText)
MsgBox ("The total number of Manifests is " & manifestTotal + 1)
Dim manifestLocation As Long
Dim numberofrowstoPage
Dim newRange As Range
Dim counter As Long
If manifestTotal = 0 Then
MsgBox ("There is only one Manifest. Macro will end.")
Else
For counter = 1 To manifestTotal
Set newRange = Range("A" & (gap + 1) & ":A1000")
manifestLocation = Application.WorksheetFunction.Match(searchText, newRange, 0) + gap
' MsgBox ("The " & counter & " manifest is on line " & manifestLocation)
numberofrowstoPage = counter * 47 - manifestLocation
' MsgBox ("The Number of Rows that will be inserted is " & numberofrowstoPage)
Rows(manifestLocation & ":" & (manifestLocation + numberofrowstoPage + 1)).Insert Shift:=xlDown
gap = 47 * counter + 2
Next counter
End If
End Sub
No need to insert an arbitrary number of rows; just set a page beak.
Sub makeReadyForPrinting()
Dim r As Long, fr As Long
With Worksheets("sheet6")
.ResetAllPageBreaks
With .Columns(1).Cells
fr = .Find(What:="Manifest Number:*", After:=.Cells(.Cells.Count), LookAt:=xlWhole, _
SearchDirection:=xlNext, SearchOrder:=xlByRows).Row
r = .FindNext(After:=.Cells(fr)).Row
Do While fr <> r
.Parent.HPageBreaks.Add Before:=.Cells(r)
r = .FindNext(After:=.Cells(r)).Row
Loop
End With
End With
End Sub
The example in your narrative included a leading space in " Manifest Number: ##### ". I've assumed that was a typo and removed it.
Related
So my problem is that for previous users who are keeping track of inventory they have labeled items with a ID of example: ABC1234 - ABC1244 but the problem is that when we keep track of our items we need each and ever individual item to be properly accounted for as each item has a unique ID that we track.
So for the past half a year we have been slowly filling in everything and since there are tons of other information in the row that is repeated I was wondering if there was a way to write a VBA macro to expand and insert these rows of data.
So from this
ID
Description
ABC1234 - ABC1237
Screw type A
to this
ID
Description
ABC1234
Screw type A
ABC1235
Screw type A
ABC1236
Screw type A
ABC1237
Screw type A
I have tried using the record macro functions but its not dynamic which is not what I want as the Database can change over time with the influx of new items so I hope there is a way to dynamically complete this process. If anyone knows a solution please help have been banging my head against a wall for awhile now :'D
not sure if this is what you are looking for.
I am assuming your ABC is always the same, the only thing that is changing is the last 4 number.
Sub Formatting()
Dim xlwrks As Object
Dim xlrng As Object
Dim xlcell As Object
Dim lowerlimit As Integer, upperlimit As Integer
Set xlwrks = ThisWorkbook.Sheets("Sheet1")
Set xlrng = xlwrks.Range("A2", xlwrks.Range("A" & Rows.Count).End(xlUp).Address) 'from A2 to last cell in column A
For Each xlcell In xlrng 'iterate ech cell from xlrng
'e.g splitting this into array of string with the delimiter " - " by using split
'which will look something like "ABC1234", "ABC1237" for A2 and "ABC1238", "ABC1242" for A3
'next we only the last 4 number, by using right
lowerlimit = Right(Split(xlcell.Value2, " - ")(0), 4)
upperlimit = Right(Split(xlcell.Value2, " - ")(1), 4)
Do Until lowerlimit = upperlimit + 1
xlwrks.Range("D" & Rows.Count).End(xlUp).Offset(1, 0).Value2 = "ABC" & lowerlimit
xlwrks.Range("D" & Rows.Count).End(xlUp).Offset(0, 1).Value2 = xlcell.Offset(0, 1).Value2
lowerlimit = lowerlimit + 1
Loop
Next xlcell
End Sub
adding on to the requirement, as mentioned, need to monitor the trend. wrote something to check for the trend instead of manually eyeball the trend. Do note with this, the run time will be longer, because it will loop through each cell to look at the array, it will also loop through each array to look at each character. hope this help happy coding!~~
Dim xlwrks As Object
Dim xlrng As Object
Dim xlcell As Object
Dim lowerlimit As Long, upperlimit As Long
Dim charpos As Integer, characters As String, ID As String
Set xlwrks = ThisWorkbook.Sheets("Sheet1")
Set xlrng = xlwrks.Range("A2", xlwrks.Range("A" & Rows.Count).End(xlUp).Address) 'from A2 to last cell in column A
For Each xlcell In xlrng 'iterate ech cell from xlrng
'e.g splitting this into array of string with the delimiter " - " by using split
'which will look something like "ABC1234", "ABC1237" for A2 and "ABC1238", "ABC1242" for A3
'next we only the last 4 number, by using right
characters = Split(xlcell.Value2, " - ")(0)
For charpos = 1 To Len(characters)
If Not IsNumeric(Mid(characters, charpos, 1)) Then
ID = ID & Mid(characters, charpos, 1)
Else
Exit For
End If
Next charpos
For charpos = 1 To Len(characters)
If IsNumeric(Mid(characters, charpos, 1)) Then
lowerlimit = CStr(lowerlimit) & CStr(Mid(characters, charpos, 1))
End If
Next charpos
characters = Split(xlcell.Value2, " - ")(1)
For charpos = 1 To Len(characters)
If IsNumeric(Mid(characters, charpos, 1)) Then
upperlimit = CStr(upperlimit) & CStr(Mid(characters, charpos, 1))
End If
Next charpos
Do Until lowerlimit = upperlimit + 1
xlwrks.Range("D" & Rows.Count).End(xlUp).Offset(1, 0).Value2 = ID & lowerlimit
xlwrks.Range("D" & Rows.Count).End(xlUp).Offset(0, 1).Value2 = xlcell.Offset(0, 1).Value2
lowerlimit = lowerlimit + 1
Loop
lowerlimit = 0
upperlimit = 0
ID = ""
Next xlcell
Honestly, I would not do this with VBA inside the spreadsheet. I would write a separate piece of VB or VBScript that reads the existing spreadsheet and produces a new altered copy of it.
When it reads a line in the original spreadsheet with just "ABC1234", it just copies that line to the new spreadsheet. When it reads a line that contains "ABC1234 - ABC1237", it recognizes the pattern and figures out how many lines it needs to generate in the new spreadsheet. In this case, it will generate four lines: one line for ABC1234, one line for ABC1235, one line for ABC1236, and one line for ABC1237.
I think this approach will be easier to deal with than a VBA script inside the spreadsheet. You will run it once, check the new spreadsheet, then rename the old one for safe-keeping, and rename the new one to give it the original sheet's name.
so essentially I have a cell that has a name, ie; "John Smith" and i want to have a button that splits the name into 2 or more pieces (depending on middle names) and pastes them into another cell.
i have the below code currently but i have no idea what im doing lol
any help would be appreciated :)
Private Sub Splitnames_Click()
Dim I As Integer
Dim WS1 As Worksheet: Set WS1 = Worksheets("sheet1")
Dim WS2 As Worksheet: Set WS2 = Worksheets("sheet2")
MyValue = InputBox("Please enter employee name...", "Import employee", "Enter employee name here...")
WS1.Range("E44").Value = MyValue
Dim FoundCell As Range: Set FoundCell = WS2.Range("A2:A1000").Find(WS1.Range("E44").Value, LookIn:=xlValues, LookAt:=xlPart)
If FoundCell Is Nothing Then
Set FoundCell = Nothing
Set WS1 = Nothing
Set WS2 = Nothing
MsgBox "No Employee found!"
Exit Sub
Else
Name = FoundCell.Offset(rowOffset:=0, columnOffset:=16).Value
SplitWords = Left(Name , 1)
For I = 2 To Len(Trim(Name ))
If (Asc(Mid(Name , I, 1)) > 64) And _
(Asc(Mid(Name , I, 1)) < 91) And _
(Mid(Name , I - 1, 1) <> " ") Then _
SplitWords = SplitWords & " "
SplitWords = SplitWords & Mid(Name , I, 1)
WS1.Range("C19") = SplitWords
Next
End If
Set FoundCell = Nothing
Set WS1 = Nothing
Set WS2 = Nothing
End Sub
I tried the above code but i cant figure out a way to paste the results into mulitple cells.
I need a way to paste result in Sheet1, Cell C19 then C20 then C21 and so forth.
This code splits the name based on where spaces are (so not exactly based on capital letters per the title of the question). To use this, remove all your code from the line SplitWords = Left(Name , 1) to Next (inclusive) and replace it with:
Dim nameArray As Variant
nameArray = Split(Name, " ")
WS1.Range("C19:C23").ClearContents
If UBound(nameArray) >= 0 Then
WS1.Range("C19").Resize(UBound(nameArray) + 1) = WorksheetFunction.Transpose(nameArray)
End If
This code assumes that your Name variable correctly has a name set into it ... I can't check that as I don't have a copy of the data in sheet1 and sheet2.
It also assumes that no name ever has more than 5 individual words ... if it does, increase the number of rows cleared in the WS1.Range("C19:C23").ClearContents line. This ensures that no individual words are left-over from previously processed names (if the previously processed name contains more individual words).
thanks for the answers, ended up going down a different route using ". " as a separator. im sure it could be modified to capital letters somehow if someone wants too see the code i came up with below;
Dim EmployeeSplit() As String, Employee As String, EI As Variant, EN As Integer
Employee = FoundCell.Offset(rowOffset:=0, columnOffset:=25).Value
If Employee = "" Then
Else
'Use Split function to divide up the component parts of the string
EmployeeSplit= Split(Employee, ". ", 4)
i = 0
For N = 0 To UBound(EmployeeSplit)
i = i + 2
'Place each split into the first column of the worksheet
WS4.Range("F" & 58 + i).Value = Replace(EmployeeSplit(N) & ". ", ". . ", ". ")
If WS4.Range("F" & 58 + i).Value = ". " Then
WS4.Range("F" & 58 + i).Value = ""
End If
Next N
End If
i used i = i + 2 because im using merged cells so i need it placed in every second cell.
I want to have a pop-up appear when the spreadsheet is opened.
Each tech is required to log their issues in the spreadsheet. When the sheet is opened, I would like it to check for the user's username against the issue list and alert them of any that have exceed their time estimate. If any issue is beyond the estimated time frame, I want the sheet to pop-up a dialog box or windows saying you have Issues A,B,C,, and that those issues need to be closed or extended.
Col A is issue Number.
Col B is the date an issue was started.
Col C is the number of Days expected for issue to be resolved (30, 60, 90, X - using a dropdown menu for these options. X Meaning it is going to be an extended time frame; unknown at entry.)
Col D is the status either Closed or Open also controlled by dropdown.
Col E is the closure date which I'm already handling using a VBA code to auto-populate when closed is chosen from dropdown.
Col F is the name of the tech handling issue.
SS of Spreadsheet
Here is where I am with the code
'DECLARE VARIABLE
Dim x_matrix As Range
Dim x_copyrange, sheet_name, issueString, currentTechName As String
Dim x_step, x_fnl_row As Long
Dim issIDCol, issStatCol, issTechCol, IssLogDateCol As Variant
Dim IssExpClosCol As Variant
'DEFINE VARIABLE
sheet_name = "Log" 'PUT YOUR SHEET NAME
issueString = "Alerts have been found to be late, Please extend or Close"
issIDCol = Columns(1) 'Put Your Report ID Column
currentTechName = Application.UserName 'returns username currently using sheet
issTechCol = Columns(6) 'The Tech name column
issStatCol = Columns(4) ' The Issue Status Column
IssLogDateCol = Columns(2) 'Column where you are logging the date issue reported
IssExpClosCol = Columns(3) '30, 60, 90, X Column
'CREATE MATRIX
x_fnl_row = Worksheets(sheet_name).Cells(Rows.Count, 1).End(xlUp).Row
'Find last row of Log # Col & used to make the loop larger each time an entry is added
Let x_copyrange = "a" & 1 & ":" & "F" & x_fnl_row
'sets a1 to bottom of last entry in F as a range
Set x_matrix = Worksheets(sheet_name).Range(x_copyrange)
'Sets the parameters for X_Matrix as a range on the worksheet
'LOOP TO
x_step = Rows(2) 'Skips the header row at the top of sheet so loop will not loop through row 1
Do While x_step <= x_fnl_row 'Sets the loop to run through the range as long as the final row is farther down then the first row
'This is your Loop
'Make your Conditions Here
'Issue is open and issue date starting is greater than expected closure date.
'Tech Names Match
If x_matrix(x_step, IssExpClosCol) <> "PPSC Closure" Then ' Xmatrix is the whole range (Xstep is the rows of range, tells it what col to search)
If x_matrix(x_step, issTechCol) = currentTechName And _
x_matrix(x_step, issStatCol) = "OPEN" And _
Now() > x_matrix(x_step, IssLogDateCol) + x_matrix(x_step, IssExpClosCol) _
Then
issueString = issueString + x_matrix(x_step, issIDCol) + ", "
End If
End If
x_step = x_step + 1
Loop
MsgBox (issueString)
End Sub
I posted some code below that works based on the how i set up my spreadsheet columns (see attached picture). I think this might be what you are asking for. Take a look see if it will work for you.
Sub standard()
'DECLARE VARIABLE
Dim x_matrix, y_matrix, z_matrix As Range
Dim x_copyrange, y_copyrange, z_copyrange, sheet_name, issueString, currentTechName As String
Dim x_step, y_step, z_step, x_fnl_row, y_fnl_row, z_fnl_row As Integer
Dim issIDCol, issStatCol, issTechCol, IssLogDateCol, IssExpClosCol As Integer
'DEFINE VARIABLE
sheet_name = "Log" 'PUT YOUR SHEET NAME
issueString = "Alerts have been found to be late, Please extend or Close"
issIDCol = 1 'Put Your Report ID Column
currentTechName = Application.UserName 'Sound like you need to add your VBA here to know the tech using the sheet
issTechCol = 6 'The Tech name column
issStatCol = 4 ' The Issue Status Column
IssLogDateCol = 2 'Column where you are logging the date issue reported
IssExpClosCol = 3 '30, 60, 90, X Column
'CREATE MATIX
x_fnl_row = Worksheets(sheet_name).Cells(Rows.Count, issIDCol).End(xlUp).Row
Let x_copyrange = "a" & 1 & ":" & "e" & x_fnl_row
Set x_matrix = Worksheets(sheet_name).Range(x_copyrange)
'LOOP TO
x_step = 2 'I am guessing you have a Header Row so start at 2
Do While x_step <= x_fnl_row
'This is your Loop
'Make your Conditions Here
'Issue is open and issue date starting is greater than expected closure date.
'Tech Names Match
If x_matrix(x_step, IssExpClosCol) <> "X" Then
If x_matrix(x_step, issTechCol) = currentTechName And _
x_matrix(x_step, issStatCol) <> "Closed" And _
Now() > x_matrix(x_step, IssLogDateCol) + x_matrix(x_step, IssExpClosCol) _
Then
issueString = issueString + x_matrix(x_step, issIDCol) + ", "
End If
End If
x_step = x_step + 1
Loop
MsgBox (issueString)
End Sub
I have a file which is modified through VBA.
It is concatenating three columns in the sheet to create a name.
However, another information needs to be concatenated to create the new data.
The data needs to be created by deducing something from data in another workbook.
In a scpecific column, with always the same name (but whose location can change, however in the sheet), the macro needs to look for a specific information. There can be four possibilities.
Once this possibility is identified, once the term is matched from either of these four, the VBA should increment the number in the end of the term in the workbook needs to be incremented.
The structure of is as follows in the first workbook:
Nip Nup Noupx
For "Noup" there are four cases : Noupx, Noupy, Noupu, Noupa
The VBA concatentes : NipNupNoupa
(or possibly NipNupNoupx, NipNupNoupu...)
Then the VBA should go in the other workbook, look for either the term "Noupa", "Noupu", "Noupx", "Noupy".
For each of these the specific number comming after "Noupa" (or the other) should be identified and should increment it by adding "+1".
Thus the result would be:
Noupa002 (resulting from the identification of Noupa001)
Noupu034 (resulting from the identificiation of Noupu033)
For the time being, I have the following VBA code, I do not know how to look for data in another workbook and increment it.
Sub TralaNome()
Const q = """"
' get source data table from sheet 1
With ThisWorkbook.Sheets(1).Cells(1, 1).CurrentRegion
' check if data exists
If .Rows.Count < 2 Or .Columns.Count < 2 Then
MsgBox "No data table"
Exit Sub
End If
' retrieve headers name and column numbers dictionary
Dim headers As Dictionary
Set headers = New Dictionary
Dim headCell
For Each headCell In .Rows(1).Cells
headers(headCell.Value) = headers.Count + 1
Next
' check mandatory headers
For Each headCell In Array(("Costumer", "ID", "Zone“, "Product Quali", "Spec A", "Spec B", "Spec_C", "Spec_D", "Spec_1", " Spec_2", " Spec_3", " Spec_4", " Spec_5", " Spec_6", " Spec_7", "Chiavetta", "Tipo_di _prodotto", "Unicorno_Cioccolato", “cacao tree“)
If Not headers.Exists(headCell) Then
MsgBox "Header '" & headCell & "' doesn't exists"
Exit Sub
End If
Next
Dim data
' retrieve table data
data = .Resize(.Rows.Count - 1).Offset(1).Value
End With
' process each row in table data
Dim result As Dictionary
Set result = New Dictionary
Dim i
For i = 1 To UBound(data, 1)
MsgBox "Empty row"
Exit For
result(result.Count) = _
q & "ID " & data(i, headers("ID ")) & _
q & " Tipo_di _prodotto " & data(i, headers("Tipo_di _prodotto")) & _
q & " cacao tree " & data(i, headers("Nupu")) & _
q
End Select
Next
' output result data to sheet 2
If result.Count = 0 Then
MsgBox "No result data for output"
Exit Sub
End If
With ThisWorkbook.Sheets(2)
.Cells.Delete
.Cells(1, 1).Resize(result.Count).Value = _
WorksheetFunction.Transpose(result.Items())
End With
MsgBox "Completed"
End Sub
The columns are grouped through this macro, but I need to now look in the other worksheet, increment the various Noupu, Noupy etc etc etc...
I think that a VBA of that sort should be used to add an incremented value :
Function GetLastRowWithData(WorksSheetNoupa As Worksheet, Optional NoupaLastCol As Long) As Long
Dim lCol, lRow, lMaxRow As Long
If NoupaLastCol = 0 Then
NoupaLastCol = wsSheet.Columns.Count
End If
lMaxRow = 0
For lCol = NoupaLastCol To 1 Step -1
lRow = wsSheet.Cells(wsSheet.Rows.Count, lCol).End(xlUp).Row
If lRow > lMaxRow Then
lMaxRow = lRow
End If
Next
GetLastRowWithData = lMaxRow
End Function
(sorry, this probably should be a comment but I don't have enough reputation as yet).
However even without checking through your code in detail, I'm seeing an exit for in the middle of a for loop without an If to avoid it in certain conditions. Presumably this means that whatever's written below that line in the loop, never gets done - nor is the loop any good for anything but the first instance. (it's the loop that's annotated 'process each row in table data)
Have you tried running this step by step? (go into the VBEditor with a test dataset open, and hit F8 or the 'step into' button in debug toolbar )
My situation is as follows. I have a list of around 2k student accounts and sort the information to a specific format that i can format to our new CRM. The way the data is presented initially makes that problematic.
As you can see on the first screenshot, every student's university choice is presented in a separate row. So if a student has chosen more than one university, data about it is stored in 2-6 rows (each student can select 1 to 6 universities) repeating his personalID, name, forename and DoB every line.
What I need to achieve is to remove repeating information and store all data about each student in one row per student(example on screenshot 2).
I have no idea how to achieve this using VBA. I was trying with IFs, loops and arrays but without any progress. I need help on how to accomplish that using VBA.
Please let me know if you need more information. I will try to explain it in more details if required.
Screenshot 1
Screenshot 2
EDIT: This is the part of the report. I am working on a macro that will format it to our needs and will give us more info about the student's accounts. That is why I am asking for help in VBA.
No need to use VBA for this. Power Query will help you better. Have a look here: https://excelgorilla.com/power-bi/power-query/aggregate-text-values-using-group-by/
This seems to work. I'm new to VBA and programming in general so it's possibly not the most efficient solution and can definitely be improved.
Instead of working with a blank sheet, it transforms the current data to the format you wanted. You can add field headings where you want.
Edit: It assumes that each Student has 5 universities in the list. The code can be adjusted to account for any number by just adjusting the target range dynamically.
Edit 2: I added the change to account for students who've entered any number of universities between 1 to 5. Let me know if this gets it done!
Sub ReArrange_Data()
Dim lrow As Long
lrow = Cells(Rows.Count, 1).End(xlUp).Row
Dim First As Integer
Dim Last As Integer
Dim test As Integer
Dim test1 As Integer
Dim student_range As Range
Dim student_rows As Integer
Dim target_range As Range
First = 2
For i = 2 To lrow
Last = First
If Cells(First, "D").Value = "" Then GoTo Break 'reached end of data
While Cells(Last, "D").Value = Cells(Last + 1, "D").Value
Last = Last + 1
Wend
If Last <> First Then 'check if mulitiple uni and build range
Set student_range = Range("E" & First & ":" & "E" & Last)
student_rows = student_range.Rows.Count
If student_rows = 5 Then
Set target_range = Range("E" & First & ":" & "I" & First)
ElseIf student_rows = 4 Then
Set target_range = Range("E" & First & ":" & "H" & First)
ElseIf student_rows = 3 Then
Set target_range = Range("E" & First & ":" & "G" & First)
ElseIf student_rows = 2 Then
Set target_range = Range("E" & First & ":" & "F" & First)
End If
Else
GoTo Skip 'student entered one uni, go to next loop
End If
target_range = Application.WorksheetFunction.Transpose(student_range.Value) 'row to column
Rows(First + 1 & ":" & Last).EntireRow.Delete
Skip: 'delete repeated entries
First = First + 1
Next i
Break:
End Sub