I wanted to insert certain number of blank columns.
For example, row 1 column 1 is Q1, and row 1 column 2 is Q2, thus I dont need to insert any blank column.
If row 1 column 4 is Q5, row 1 column 3 is Q3, thus i want to insert (5-3-1) 1 blank column, a column to accommodate for Q4
Picture of the table is attached below.
https://imgur.com/NSatL9w
Sorry this is my first time writing on VBA. Any help is greatly appreciated.
Updated
Below is the error message displayed.
Compile error: Expected array
Option Explicit
Sub Test()
Dim lCol As Integer
Dim pos() As Long
Dim pos1() As Long
Dim strString() As String
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
For i = 1 To lCol
If Left(Sheets(1).Cells(1, i).Value, 1) = "Q" Then
pos(i) = InStr(1, Cells(1,i), "Q") + 1
pos1(i) = InStr(pos(i), Cells(1,i), "<")
strString(i) = Mid(Cells(1,i), pos(i), pos1(i) - pos(i))
If strString(i + 1) - strString(i) > 1 Then
Columns(strString(i)+1:strString(i+1)-1).Insert
Shift:=xlToRight
End If
End If
Next i
End Sub
You have declared pos, pos1 and strStringas Integers then in your code you are using them as Arrays: pos(i), pos1(i), and strString(i+1). That is why you are getting the compile error Expected Array.
Also, when adding rows you need to move from the bottom up or adding columns from right to left. your counter should go from lCol to 1 Step -1.
You need to fully qualify your objects as well. Cells with no qualifier for which sheet will use whatever sheet is the active sheet, not necessarily the one you want to affect.
For the specific error, the variables pos, pos1 and strString need to be declared as arrays as we store multiple values and not only a single one.
This could be done in several difference ways:
'Method 1 : Using Dim
Dim arr1() 'Without Size
'Method 2 : Mentioning the Size
Dim arr2(5) 'Declared with size of 5
'Method 3 : using 'Array' Parameter
Dim arr3
arr3 = Array("apple","Orange","Grapes")
I will use Method 1, and after I know how many columns we need, I will resize/define the array so it will look like Method 2.
ActiveCell will not work as it refer to a single selection, so we need to change that to a dynamic reference.
Since you will add columns, your "total" range will be change for each inserted column. So if you have 14 columns from the beginning, you might miss the last ones as your range will have increased. I therefore recommend to start from right and loop to the left.
I also automatically added the headers for the new inserted column. Thought it could be a nice feature.
This code is hopefully something that can help you along:
Option Explicit
Sub test()
Dim lCol As Integer
Dim pos() 'Dim the variable as Array
Dim pos1() 'Dim the variable as Array
Dim strString() 'Dim the variable as Array
Dim i As Long 'Dim the variable i which will hold the position
Dim j As Long 'Dim the variable j which will loop for new inserted headers
Dim k As Long 'Dim the dummy variable k which will add one number for each empty header, between two quarters
lCol = Cells(1, Columns.Count).End(xlToLeft).Column 'Find the last column to loop through
ReDim pos(0 To lCol) 'When we know how many columns to loop through we can resize our array for the variable pos
ReDim pos1(0 To lCol) 'Same logic as above
ReDim strString(0 To lCol) 'Same logic as above
For i = lCol + 1 To 1 Step -1 'Since we want to insert a new column our "complete range will change". Therefore we start backwards and to Column A
If Left(Sheets(1).Cells(1, i).Value, 1) = "Q" Then 'Check if cell in row 1 starts with letter Q
pos(i) = InStr(1, Cells(1, i), "Q") + 1 'Get position for Q and add 1
pos1(i) = InStr(pos(i), Cells(1, i), "<") 'Get position for sign "<"
strString(i) = Mid(Cells(1, i), pos(i), pos1(i) - pos(i)) 'Extract the difference between "pos" and "pos1" to get which quarter we are dealing with
If ((strString(i + 1)) - strString(i)) > 1 And Not IsEmpty(strString(i + 1)) Then 'If the difference between cell "i +1" - cell "i" is larger than 1, and cell "i+1" is not empty, then..
Columns(i + 1).Resize(, ((strString(i + 1)) - strString(i)) - 1).Insert '... We use the difference between the cells and then resize our range which we want to insert
'### this part is only to create the header automatically, can be removed. ###
If ((strString(i + 1)) - strString(i)) > 2 Then 'If the difference is larger than 2, it means that we need to insert at least 2 columns or more
k = 1 'Set dummy variable k to 1
For j = i + 1 To strString(i) + (((strString(i + 1)) - strString(i)) - 1) 'Loop through the new empty inserted columns and add quarter headers
Cells(1, j).Value = "Q" & strString(i) + k & "<>"
k = k + 1 'Add one quarter
Next j
Else
Cells(1, i + 1).Value = "Q" & strString(i + 1) - ((strString(i + 1) - strString(i)) - 1) & "<>" 'Add Quarter headers if only one column was inserted
End If
'### --------------------------------------------------------------------- ###
End If
End If
Next i
End Sub
Final result:
you could avoid arrays:
Option Explicit
Sub Test()
Dim lCol As Long, i As Long
Dim qCurrent As Long, qPreceeding As Long
With Sheets(1) 'reference your sheet
lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column ' start from referenced sheet row 1 last not empty column index
Do While lCol > 1 ' start iterating from last column
If Left(.Cells(1, lCol).Value, 1) = "Q" Then
qCurrent = Val(Mid(.Cells(1, lCol).Value, 2)) ' get current column"Q" value
qPreceeding = Val(Mid(.Cells(1, lCol - 1).Value, 2)) ' get preceeding column"Q" value
If qCurrent > qPreceeding + 1 Then ' if current "Q" is not consecutive of preceeding one
.Cells(1, lCol).EntireColumn.Resize(, qCurrent - qPreceeding - 1).Insert ' insert columns
For i = 1 To qCurrent - qPreceeding - 1 'loop to recreate new headers
.Cells(1, lCol + i - 1).Value = "Q" & qPreceeding + i & "<>"
Next
End If
End If
lCol = lCol - 1 ' step backwards
Loop
End With
End Sub
Related
I am new to VBA and am trying to copy the column from Row 2 onwards where the column header (in Row 1) contains a certain word- "Unique ID".
Currently what I have is:
Dim lastRow As Long
lastRow = ActiveWorkbook.Worksheets("Sheets1").Range("A" & Rows.Count).End(xlUp).Row
Sheets("Sheets1").Range("D2:D" & lastRow).Copy
But the "Unique ID" is not always in Column D
You can try following code, it loops through first row looking for a specified header:
Sub CopyColumnWithHeader()
Dim i As Long
Dim lastRow As Long
For i = 1 To Columns.Count
If Cells(1, i) = "Unique ID" Then
lastRow = Cells(Rows.Count, i).End(xlUp).Row
Range(Cells(2, i), Cells(lastRow, i)).Copy Range("A2")
Exit For
End If
Next
End Sub
When you want to match info in VBA you should use a dictionary. Additionally, when manipulating data in VBA you should use arrays. Although it will require some learning, below code will do what you want with minor changes. Happy learning and don't hesitate to ask questions if you get stuck:
Option Explicit
'always add this to your code
'it will help you to identify non declared (dim) variables
'if you don't dim a var in vba it will be set as variant wich will sooner than you think give you a lot of headaches
Sub DictMatch()
'Example of match using dictionary late binding
'Sourcesheet = sheet1
'Targetsheet = sheet2
'colA of sh1 is compared with colA of sh2
'if we find a match, we copy colB of sh1 to the end of sh2
'''''''''''''''''
'Set some vars and get data from sheets in arrays
'''''''''''''''''
'as the default is variant I don't need to add "as variant"
Dim arr, arr2, arr3, j As Long, i As Long, dict As Object
'when creating a dictionary we can use early and late binding
'early binding has the advantage to give you "intellisense"
'late binding on the other hand has the advantage you don't need to add a reference (tools>references)
Set dict = CreateObject("Scripting.Dictionary") 'create dictionary lateB
dict.CompareMode = 1 'textcompare
arr = Sheet1.Range("A1").CurrentRegion.Value2 'load source, assuming we have data as of A1
arr2 = Sheet2.Range("A1").CurrentRegion.Value2 'load source2, assuming we have data as of A1
'''''''''''''''''
'Loop trough source, calculate and save to target array
'''''''''''''''''
'here we can access each cell by referencing our array(<rowCounter>, <columnCounter>
'e.g. arr(j,i) => if j = 1 and i = 1 we'll have the values of Cell A1
'we can write these values anywhere in the activesheet, other sheet, other workbook, .. but to limit the number of interactions with our sheet object we can also create new, intermediant arrays
'e.g. we could now copy cel by cel to the new sheet => Sheets(arr(j,1).Range(... but this would create significant overhead
'so we'll use an intermediate array (arr3) to store the results
'We use a "dictionary" to match values in vba because this allows to easily check the existence of a value
'Together with arrays and collections these are probably the most important features to learn in vba!
For j = 1 To UBound(arr) 'traverse source, ubound allows to find the "lastrow" of the array
If Not dict.Exists(arr(j, 1)) Then 'Check if value to lookup already exists in dictionary
dict.Add Key:=arr(j, 1), Item:=arr(j, 1) 'set key if I don't have it yet in dictionary
End If
Next j 'go to next row. in this simple example we don't travers multiple columns so we don't need a second counter (i)
'Before I can add values to a variant array I need to redim it. arr3 is a temp array to store matching col
'1 To UBound(arr2) = the number of rows, as in this example we'll add the match as a col we just keep the existing nr of rows
'1 to 1 => I just want to add 1 column but you can basically retrieve as much cols as you want
ReDim arr3(1 To UBound(arr2), 1 To 1)
For j = 1 To UBound(arr2) 'now that we have all values to match in our dictionary, we traverse the second source
If dict.Exists(arr2(j, 1)) Then 'matching happens here, for each value in col 1 we check if it exists in the dictionary
arr3(j, 1) = arr(j, 2) 'If a match is found, we add the value to find back, in this example col. 2, and add it to our temp array (arr3).
'arr3(j, 2) = arr(j, 3) 'As explained above, we could retrieve as many columns as we want, if you only have a few you would add them manually like in this example but if you have many we could even add an additional counter (i) to do this.
End If
Next j 'go to the next row
'''''''''''''''''
'Write to sheet only at the end, you could add formatting here
'''''''''''''''''
With Sheet2 'sheet on which I want to write the matching result
'UBound(arr2, 2) => ubound (arr2) was the lastrow, the ubound of the second dimension of my array is the lastcolumn
'.Cells(1, UBound(arr2, 2) + 1) = The startcel => row = 1, col = nr of existing cols + 1
'.Cells(UBound(arr2), UBound(arr2, 2) + 1)) = The lastcel => row = number of existing rows, col = nr of existing cols + 1
.Range(.Cells(1, UBound(arr2, 2) + 1), .Cells(UBound(arr2), UBound(arr2, 2) + 1)).Value2 = arr3 'write target array to sheet
End With
End Sub
So I have an excel sheet that can have anywhere from 5-1500 lines. Most lines have: 1) Title Row, 2) patient information, 3) blank row. Then it repeats. Some lines have 1) Title Row, 2) patient info, 3) additional patient info, 4)blank row. I need to insert a line between Rows 2&3 if there is info in row 3. Does this make sense?
Example:
--------A---------------------b-----------------c-------------------d--------
1-----acct #--------patient name------dr name------ date of service
2------123456-------Mickey Mouse-----Donald Duck--------1/4/19
3----------((((((((((((((all of this row is blank)))))))))))))))))))))----------
Or it could be this:
--------A---------------------b--------------------c-------------------d------
1-----acct #--------patient name--------dr name------ date of service
2------123456-------Mickey Mouse-----Donald Duck--------1/4/19
3------123456-------Mickey Mouse-----Donald Duck--------1/4/19
4----------((((((((((((((all of this row is blank)))))))))))))))))))))----------
Then this same format repeats throughout the sheet with different info of course. What I need is if row 3 has any info then insert a row between tows 2 & 3, but if row 3 is blank then skip to the next set.
This is the code I have so far but it is adding rows every other row no matter what.
Sub Macro()
Dim lastRow As Integer
lastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.count).Row
Dim I As Long
For I = 6 To lastRow
If Cells(I + 2, 9).Text <> "" Then
Rows(I + 1).EntireRow.Insert Shift:=xlDown
lastRow=lastRow+1
End If
Next I
End Sub
As #BruceWayne stated in the comments, When inserting or deleting rows, columns or cells, it's helpful to iterate backwards. The Step parameter of a For-Next loop allows you to define how you would like to iterate. It defaults to Step 1. So instead of iterating from I = 6 to lastRow try
Dim lastRow As Long
Dim i As Long
lastRow = ActiveSheet.UsedRange.Rows(ActiveSheet.UsedRange.Rows.Count).Row
For i = lastRow To 6 Step -1
If Cells(i - 1, 9).Text <> "" And Cells(i, 9).Text <> "" Then
Rows(i).EntireRow.Insert Shift:=xlDown
End If
Next i
This would insert a row at your current iteration if both the current cell and the cell above it had data in them.
It's worth noting that if you were to iterate to row 1, the If statement above would raise an error, but you'd never need to.
EDIT:
If what you need is to only add a row between patient info and additional patient info, you'd need to find a consistently identifiable piece of data to add as a condition to the If statement.
Give this a try.
Customize the variables to fit your needs
Sub InsertRows()
' Define object variables
Dim rangeEval As Range
Dim currentCell As Range
' Define other variables
Dim sheetName As String
Dim rowCounter As Integer
' >>>> Customize this
sheetName = "Sheet1"
' Initialize the used range in column A ' Change the number in .Columns(1) to use another column
Set rangeEval = ThisWorkbook.Worksheets(sheetName).UsedRange.Columns(1)
' Loop through each cell in range
For Each currentCell In rangeEval.Cells
' We use this counter to check if we are every third row
rowCounter = rowCounter + 1
' If this is the third row and there is something in the cell, insert one row
If rowCounter Mod 3 = 0 And currentCell.Value <> vbNullString Then
currentCell.EntireRow.Insert
' Reset the counter if there is nothing in the cell
ElseIf currentCell.Value = vbNullString Then
rowCounter = 0
End If
Next currentCell
End Sub
I want to copy & paste every 10 rows, 10 times from column A to column B and so on continuing until the end of column A.
This is an example of macro I've tried:
Sub cpydble()
Dim j As Long
Dim i As Long
Dim lRow As Long
lRow = Cells(Rows.Count, 1).End(xlUp).row
For i = 1 To lRow Step 10
For j = 1 To 100 Step 10
Cells(i, 1).Resize(10).Copy Destination:=Cells(j, 2)
Next j
Next i
End Sub
I'm a beginner with VBA and hope you can help with this - thanks in advance.
This is my current result:
You could use:
For i = 1 To lRow Step 10
Range("B" & i & ":B" & i + 9).Value = Range("A1:A10").Value
Next i
Note that with the above code, the last iteration will go below the last row in column A should it not be a multiple of 10.
Starting j at 1 every time is probably what's messing stuff up. Just find the next open cell for every loop.
Sub cpydbl()
Dim i As Long, j As Long
Dim lRow As Long
lRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lRow Step 10
For j = 1 To 10
Cells(i, 1).Resize(10).Copy Cells(Rows.Count, 2).End(xlUp).Offset(1, 0)
Next j
Next i
Cells(1, 2).Delete xlShiftUp
End Sub
The Offset starts the copy at row 2, so I delete the empty first cell at the end to move everything up.
Fully flexibilized code
In addition to #DickKusleika 's fine code, I demonstrate a fully flexibilized approach using a data array where you can define alternative block size, number of repetitions and start row via constants.
Option Explicit ' declaration head of your code module
Sub copyBlocks()
Const SIZE& = 10, REPETITIONS& = 10, STARTROW& = 1 ' define block size, repetions and start row
Dim ws As Worksheet, i&, j&, k&, n&, v ' declare variables
Set ws = ThisWorkbook.Worksheets("MySheet") ' << change to your sheet name
n = ws.Range("A" & ws.Rows.Count).End(xlUp).Row ' find last row number in column A
n = ((n + SIZE) \ SIZE) * SIZE ' round up to full block size of 10 rows
ws.Range("B:B") = "" ' clear column B
k = STARTROW ' start row of 1st block series
For i = STARTROW To n Step SIZE ' if STARTROW = 1 For i=1, 11, 21, 31 ... To n
v = ws.Range("A" & i).Resize(SIZE) ' get next data block (10 rows)
For j = 1 To REPETITIONS ' write eg. 10 data blocks to column B
ws.Range("B" & (k + (j - 1) * SIZE)).Resize(SIZE) = v
Next j
k = k + SIZE * REPETITIONS ' get start row of next block series
Next i
End Sub
Notes
Declare your variables (and their types) and force yourself to do so by stating Option Explicit in the declaration head of your code module; the ampersand sign & is short for e.g. Dim i As Long. v and all not explicitly declared variables default to Variant.
Always use fully qualified range references, otherwise values default to the active sheet which might result in wrong values.
Variable n finds the last row number in column A and rounds it up to the full block size of 10 rows.
You can easily assign range values to a variant 2-dimensional array in one code line, e.g. via v = ws.Range("A1:E1234") or v = ws.Range("A1:A17").Value. Further hint Each member of this array could be addressed by row and column indices. Note that data field arrays getting values from worksheet ranges are 1-based, so the first value would be addressed as v(1,1).
I have the following data.
If the same task appears more than 2 rows, I need to delete the 3rd, 4th,...duplicate rows. The rows are already sorted by Task name and date modified. I only need the most current and 1 prior data (first 2 rows of the same task).
In the above image, Row 7, 8, 9, 13, 14, 15, 16, 17, ... should be deleted
This isn't as easy to pull of as it first seems it might be. Every time we loop rows and delete the row based on some criteria we run into issues. We delete the row we are on, and then move to the next row, but because we deleted the row we are on, we are already on the next row. It's like pulling the rug out from underneath us while we are walking.
To get around these we usually step backwards through a range and delete, but... because in this case we are only deleting based on what we've already found, we have to go forwards.
There's a few ways to deal with this. I think the safest and most robust way is by looping once to get a count of each term, then looping again and deleting the appropriate amount of rows based on what we found in the first loop. This way we have LOTS of control over what gets deleted and how far we step in each iteration. It also reduces the complexities that we would face in tracking what we've found, how much of it, if we need to delete the current row, and how to deal with the loop if we do.
Sub removeRows()
Dim rngRow As Range
Dim dictTerms As Scripting.Dictionary
'Initialize Dictionary
Set dictTerms = New Scripting.Dictionary
'Load up dictionary using the term as the key and the count as the value
' by looping through each row that holds the terms
For Each rngRow In Sheet1.Rows("3:17")
'Only upsert to dictionary if we have a valule
If rngRow.Cells(1, 1).Value <> "" Then
If dictTerms.Exists(rngRow.Cells(1, 1).Value) Then
'increment value
dictTerms(rngRow.Cells(1, 1).Value) = dictTerms(rngRow.Cells(1, 1).Value) + 1
Else
'Add to dictionary with value 1
dictTerms.Add Key:=rngRow.Cells(1, 1).Value, Item:=1
End If
End If
Next rngRow
Dim intRow As Integer: intRow = 3
Dim intCounter As Integer
Dim termCount As Integer
'Loop through rows starting at intRow(set to 3 above) and ending at 17 (possible max)
Do While intCounter <= 17
'Skip blank rows
If Sheet1.Cells(intRow, 1).Value <> "" Then
'grab the number of terms encounterd so we know how much to delete
termCount = dictTerms(Sheet1.Cells(intRow, 1).Value)
'If it's more than two, then delete the remaining
If termCount > 2 Then Sheet1.Rows(intRow + 2 & ":" & intRow + termCount - 1).Delete
'Increment past what we deleted (or found if we didn't delete anything)
intRow = intRow + 2 + (termCount <> 1)
'Set the loop counter.
intCounter = intCounter + termCount
Else
'We found a blank, just increment our loop counter
intCounter = intCounter + 1
intRow = intRow + 1
End If
Loop
End Sub
You'll need to go to Tools>>References and add Microsoft Scripting Runtime (check the checkbox next to it in the big list and hit OK) so we can use the Scripting.Dictionary.
You'll also need to edit references to Sheet1 to whatever Sheet you are on. And possibly references to Cells(1,1) changing that first 1 to whatever column we are analyzing (assumed Column "A" here). Lastly you'll need to tweak startRow and endRow setting those values to whatever is appropriate for you workbook.
#JNevill, when you mentioned counter for each task, I just thought of something simple, -- now I just need to figure out how to delete the rows with values greater than 2 in the new column...without getting the error Script out of Range or Delete Method of Range Class Failed
'Declare Variables
Dim tableName As String
Dim activeSheetName As String
Dim totalrows As Long
'Identify Active Sheet Name
activeSheetName = ActiveSheet.Name
'Identify Active Table Name
tableName = ActiveSheet.ListObjects(1).Name
'Identify total number of rows
totalrows = Worksheets(activeSheetName).Range(tableName).Rows.count '99
'Insert counter column
Columns("B:B").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Dim taskCounter As Long
Dim rowNum As Integer
rowNum = 2
taskCounter = 0
For a = 1 To totalrows + 1
If Range("A" & rowNum) = "" Then
taskCounter = 0
Range("B" & rowNum).Value = taskCounter
Else
taskCounter = taskCounter + 1
Range("B" & rowNum).Value = taskCounter
End If
rowNum = rowNum + 1
Next a
I need to find a way to split some data on excel: e.g.
If a cell has the following in: LWPO0001653/1654/1742/1876/241
All of the info after the / should be LWPO000... with that number.
Is there anyway of separating them out and adding in the LWPO000in? So they come out as LWPO0001653
LWPO0001654
etc etc
I could do manually yes, but i have thousands to do so would take a long time.
Appreciate your help!
Here is a solution using Excel Formulas.
With your original string in A1, and assuming the first seven characters are the one's that get repeated, then:
B1: =LEFT($A1,FIND("/",$A1)-1)
C1: =IF(LEN($A1)-LEN(SUBSTITUTE($A1,"/",""))< COLUMNS($A:A),"",LEFT($A1,7)&TRIM(MID(SUBSTITUTE(MID($A1,8,99),"/",REPT(" ",99)),(COLUMNS($A:A))*99,99)))
Select C1 and fill right as far as required. Then Fill down from Row 1
EDIT: For a VBA solution, try this code. It assumes the source data is in column A, and puts the results adjacent starting in Column B (easily changed if necessary). It works using arrays within VBA, as doing multiple worksheet read/writes can slow things down. It will handle different numbers of splits in the various cells, although could be shortened if we knew the number of splits was always the same.
Option Explicit
Sub SplitSlash()
Dim vSrc As Variant
Dim rRes As Range, vRes() As Variant
Dim sFirst7 As String
Dim V As Variant
Dim COL As Collection
Dim I As Long, J As Long
Dim lMaxColCount As Long
Set rRes = Range("B1") 'Set to A1 to overwrite
vSrc = Range("a1", Cells(Rows.Count, "A").End(xlUp))
'If only a single cell, vSrc won't be an array, so change it
If Not IsArray(vSrc) Then
ReDim vSrc(1 To 1, 1 To 1)
vSrc(1, 1) = Range("a1")
End If
'use collection since number of columns can vary
Set COL = New Collection
For I = 1 To UBound(vSrc)
sFirst7 = Left(vSrc(I, 1), 7)
V = Split(vSrc(I, 1), "/")
For J = 1 To UBound(V)
V(J) = sFirst7 & V(J)
Next J
lMaxColCount = IIf(lMaxColCount < UBound(V), UBound(V), lMaxColCount)
COL.Add V
Next I
'Results array
ReDim vRes(1 To COL.Count, 1 To lMaxColCount + 1)
For I = 1 To UBound(vRes, 1)
For J = 0 To UBound(COL(I))
vRes(I, J + 1) = COL(I)(J)
Next J
Next I
'Write results to sheet
Set rRes = rRes.Resize(UBound(vRes, 1), UBound(vRes, 2))
With rRes
.EntireColumn.Clear
.Value = vRes
.EntireColumn.AutoFit
End With
End Sub
I'm clearly missing the point :-) but anyway, in B1 and copied down to suit:
=SUBSTITUTE(A1,"/","/"&LEFT(A1,7))
Select ColumnB, Copy and Paste Special, Values over the top.
Apply Text to Columns to ColumnB, Delimited, with / as the delimiter.
There's a couple of ways to solve this. The quickest is probably:
Assuming that the data is in column A:
Highlight the column, go to Data>>Text To Columns
Choose "Delimited" and in the "Other" box, put /
Click ok. You'll have your data split into multiple cells
Insert a column at B and put in the formula =Left(A1, 7)
Insert a column at C and pit in formula =Right(A1, Length(A1)-7)
You'll now have Column B with your first 7 characters, and columns B,C,D,E,F, etc.. with the last little bit. You can concatenate the values back together for each column you have with =Concatenate(B1,C1), =Concatenate(B1,D1), etc..
A quick VBa, which does nearly the same thing that #Kevin's does as well. I wrote it before I saw his answer, and I hate to throw away work ;)
Sub breakUpCell()
Dim rngInput As Range, rngInputCell As Range
Dim intColumn As Integer
Dim arrInput() As String
Dim strStart As String
Dim strEnd As Variant
'Set the range for the list of values (Assuming Sheet1 and A1 is the start)
Set rngInput = Sheet1.Range("A1").Resize(Sheet1.Range("A1").End(xlDown).Row)
'Loop through each cell in the range
For Each rngInputCell In rngInput
'Split up the values after the first 7 characters using "/" as the delimiter
arrInput = Split(Right(rngInputCell.Value, Len(rngInputCell.Value) - 7), "/")
'grab the first 7 characters
strStart = Left(rngInputCell.Value, 7)
'We'll be writing out the values starting in column 2 (B)
intColumn = 2
'Loop through each split up value and assign to strEnd
For Each strEnd In arrInput
'Write the concatenated value out starting at column B in the same row as rngInputCell
Sheet1.Cells(rngInputCell.Row, intColumn).Value = strStart & strEnd
'Head to the next column (C, then D, then E, etc)
intColumn = intColumn + 1
Next strEnd
Next rngInputCell
End Sub
Here is how you can do it with a macro:
This is what is happening:
1) Set range to process
2) Loop through each cell in range and check it isn't blank
3) If the cell contains the slash character then split it and process
4) Skip the first record and concatenate "LWPO000" plus the current string to adjacent cells.
Sub CreateLWPO()
On Error Resume Next
Application.ScreenUpdating = False
Dim theRange
Dim cellValue
Dim offset As Integer
Dim fields
'set the range of cells to be processed here
Set theRange = range("A1:A50")
'loop through each cell and if not blank process
For Each c In theRange
offset = 0 'this will be used to offset each item found 1 cell to the right (change this number to this first column to be populated)
If c.Value <> "" Then
cellValue = c.Value
If InStr(cellValue, "/") > 0 Then
fields = Split(cellValue, "/")
For i = 1 To UBound(fields)
offset = offset + 1
cellValue = "LWPO000" & fields(i)
'if you need to pad the number of zeros based on length do this and comment the line above
'cellValue = "LWPO" & Right$(String(7, "0") & fields(i), 7)
c.offset(0, offset).Value = cellValue
Next i
End If
End If
Next
Application.ScreenUpdating = True
End Sub