How to change the number of digits based on previous column? - excel

This builds off of this question Using Left without Copy & Paste
I need to conditionally format these columns depending on the company in the column before. Here is the coding that works:
Sub keep12()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim rng As Range
Set rng = wks.Range("C3:C" & wks.Range("C" & wks.Cells.Rows.Count).End(xlUp).Row)
'set column C as Number (if this step is skipped it can go to Scientific and that doesn't work)
Columns("C:C").Select
Application.CutCopyMode = False
Selection.NumberFormat = "0.00"
Selection.NumberFormat = "0"
For Each Cell In rng
Cell.Value = Left(Cell.Text, 12)
Next Cell
End Sub
basically I want to go one step further and if Column B (company codes) are ABC, DEF, or GHI, then format the cell next to it in C as 10 digits, for any other info in column B (JKL, MNO, etc) then set it as 12. I'm guessing I could use a For Each, Select Case sort of thing? But I'm not entirely sure how to do this. Any help would be greatly appreciated.

Sub keep12()
Dim wks As Worksheet
Set wks = Worksheets("Sheet1")
Dim rng As Range
Set rng = wks.Range("C3:C" & wks.Range("C" & wks.Cells.Rows.Count).End(xlUp).Row)
'set column C as Number (if this step is skipped it can go to Scientific and that doesn't work)
Columns("C:C").Select
Application.CutCopyMode = False
Selection.NumberFormat = "0.00"
Selection.NumberFormat = "0"
For Each cell In rng
Select Case cell.Offset(0, -1)
Case "ABC", "DEF", "GHI"
cell.Value = Left(cell.Text, 10)
Case Else
cell.Value = Left(cell.Text, 12)
End Select
Next cell
End Sub

Related

How to divide every cell in a column by a constant in VBA?

I am processing a data set that has about 50 columns, and the same columns are always off by a factor of ten. So, I just want to hardcode the specific columns (starting with F here) and divide every cell in the column by 10. Right now I am getting a "Type Mismatch" error. The code is below:
Sub FixData()
Dim finalRow As Long
Dim rng As Range
Dim cell As Range
finalRow = Range("A100000").End(xlUp).Row
Set rng = Range("F1:F" & finalRow)
For Each cell In rng
cell.Value = cell.Value / 10
Next cell
End Sub
why loop when you can simply paste special and divide.
errors within the cells are ignored.
in vba, here is the code
Range("G10").Copy
Range("B2:E8").PasteSpecial Paste:=xlPasteValues, Operation:=xlDivide
Application.CutCopyMode = False
test if cell is an error and then test if it is a number prior to dividing:
Sub FixData()
Dim finalRow As Long
Dim rng As Range
Dim cell As Range
finalRow = Range("A100000").End(xlUp).Row
Set rng = Range("F1:F" & finalRow)
For Each cell In rng
If Not IsError(Cell) Then
If IsNumeric(cell) and cell <> "" Then
cell.Value = cDbl(cell.Value) / 10
End If
End If
Next cell
End Sub

Find a string from Cell, and delete 4-5 rows attached to it and then move to next cell

What I'm looking for is, I need to find out if a cell contains ".L" in it, if yes, the entire row along with 4 more rows needs to be deleted and this series goes on until last set of data.
For example:
There would be hundreds of dataset like shown below, out of which "RIC" contains ".L".
TID: xxx, Symbol=xxx, Date=xxx, RIC=EPWN.L , CUSIP=xxx, SEDOL=xxx
DataStream: xxxx
Bloomberg.: xxxx
Market....: xxxx
TID: xxx, Symbol=xxx, Date=xxx, RIC=BAR.BR , CUSIP=xxx, SEDOL=xxx
DataStream: xxx
Bloomberg.: xxx
Market....: xxx
Need to delete the entire set if any RIC is having ".L". So in the end, what should I get is dataset without ".L"
Please help
Below is the vba but it is not working:
Range("b2:b2000").ClearContents
Dim rng As Range
Dim cell As Range
Dim serchstring As String
Set rng = ActiveSheet.UsedRange
searchstring = ".l"
On Error Resume Next
For Each cell In rng
If UCase(cell.Value) Like "*" & UCase(searchstring) Then
cell.Offset(0, 1).Value = "NA"
cell.Offset(1, 1).Value = "NA"
cell.Offset(2, 1).Value = "NA"
cell.Offset(3, 1).Value = "NA"
cell.Font.Bold = True
cell.Interior.Color = vbYellow
End If
Next cell
Cells.Select
With ActiveSheet
.AutoFilterMode = False
.Range("A:B").AutoFilter
.Range("A:B").AutoFilter field:=2, Criteria1:="NA"
Intersect(.UsedRange, .UsedRange.Offset(1)).SpecialCells(xlCellTypeVisible).EntireRow.Delete
.AutoFilterMode = False
End With
With ActiveSheet
.AutoFilterMode = False
.Range("A:B").AutoFilter field:=1, Criteria1:=""
Intersect(.UsedRange, .UsedRange.Offset(1)).SpecialCells(xlCellTypeVisible).EntireRow.Delete
.AutoFilterMode = False
End With
If your program is not erasing the row, I think the issue lies with these lines:
cell.Offset(0, 1).Value = "NA"
cell.Offset(1, 1).Value = "NA"
cell.Offset(2, 1).Value = "NA"
cell.Offset(3, 1).Value = "NA"
Offset is returning a single cell so you are only erasing a single cell. But your post says you want to erase the whole row. To reference the row, I suggest:
cell.Offset(0, 1).EntireRow.ClearContents
cell.Offset(1, 1).EntireRow.ClearContents
cell.Offset(2, 1).EntireRow.ClearContents
cell.Offset(3, 1).EntireRow.ClearContents
Which can be reduced to a single line like:
cell.Offset(0).Resize(4).EntireRow.ClearContents
Or if you don't want to leave blank rows behind you can directly delete the rows like:
cell.Offset(0).Resize(4).EntireRow.Delete
But if you do repetitive deleting, you'll notice that Excel stutters and the execution is slow. So I suggest saving the rows to be deleted into a range variable and then deleting them all at once at the end. Use Union() to add ranges together.
If rToBeDeleted Is Nothing Then
Set rToBeDeleted = cell.Offset(0).Resize(4).EntireRow
Else
Set rToBeDeleted = Union(rToBeDeleted, cell.Offset(0).Resize(4).EntireRow)
End If
'And then at the end
rToBeDeleted.Delete
And if you do it this way, you don't need to do any of that autofilter deleting.
Edit:
For clarity, here is how I suggest your code be structured after applying my suggestions:
Range("b2:b2000").ClearContents
Dim rng As Range
Dim cell As Range
Dim rToBeDeleted As Range
Dim serchstring As String
Set rng = ActiveSheet.UsedRange
searchstring = "*.L"
On Error Resume Next
For Each cell In rng
If UCase(cell.Value) Like searchstring Then
If rToBeDeleted Is Nothing Then
Set rToBeDeleted = cell.Offset(0).Resize(4).EntireRow
Else
Set rToBeDeleted = Union(rToBeDeleted, cell.Offset(0).Resize(4).EntireRow)
End If
End If
Next cell
rToBeDeleted.Delete

Split zip code in a column into 2 columns

This is what my end result should look like. If there is not the four digits to move over to the second column then fill with 4 zeros.
How can I split zip code in a column into 2 columns and fill empty cells in column 2 if first column has only 5 digits?
Here is what I have been working with
Dim ws As Worksheet
Dim cell As Range
Set ws = Worksheets("sheet1")
For Each cell In ws.Range("K2:K500").Cells
cell.Offset(0, 1).Value = Left(cell.Value, 5)
Next cell
Dim cel As Range, rngC As Range, rngB As Range
Dim lastRowA As Long, lastRowB As Long
With ws
lastRowK = .Cells(.Rows.Count, "K").End(xlUp).Row 'last row of column A
lastRowL = .Cells(.Rows.Count, "L").End(xlUp).Row 'last row of column B
For Each cel In .Range("K2:K" & lastRowL) 'loop through column L
'check if cell in column A exists in column B
If WorksheetFunction.CountIf(.Range("K2:K" & lastRowL), cel) = 0 Then
cel.Offset(0, 3).Value = Right(cel.Value, 4)
'.Range("M" & cel.Row) = Right(cell.Value, 4)
Else
.Range("M" & cel.Row) = "0000"
End If
Next
End With
In case you want to bypass VBA and use formulas, you can do this.
Cell B2:
=LEFT(A2,5)
Cell C2:
=IF(LEN(A2)=9,RIGHT(A2,4),"0000")
One of the simplest ways to solve this problem is to supplement the original string with a large number of zeros and take the values ​​of the first and second five characters for two cells:
Sub setZIPandZeros()
Const TEN_ZEROS = "0000000000" ' 10 times
Dim ws As Worksheet
Dim cell As Range
Dim sLongString As String
Set ws = Worksheets("Sheet1")
For Each cell In ws.Range("K2:K" & ws.Cells(ws.Rows.Count, "K").End(xlUp).Row).Cells
sLongString = Trim(cell.Text) & TEN_ZEROS
cell.Offset(0, 1).Resize(1, 2).NumberFormat = "#"
cell.Offset(0, 1).Resize(1, 2).Value = Array(Left(sLongString, 5), _
Mid(sLongString, 6, 5))
Next cell
End Sub
Update The modified code is much faster and gives a result that more closely matches the description of the task:
Sub setZipZeros()
Dim ws As Worksheet
Dim rResult As Range
Set ws = Worksheets("Sheet1")
' Addressing R1C1 is used in the formulas - If the original range
' is shifted to another column, you will need to change the letter
' of the column "K" only in this line
Set rResult = ws.Range("K2", ws.Cells(ws.Rows.Count, "K").End(xlUp)).Offset(0, 1)
' If the columns L:M are already in text format, then instead of
' the results we will get the texts of formulas
rResult.Resize(, 2).NumberFormat = "General"
' These two lines do most of the work:
rResult.Formula2R1C1 = "=LEFT(TRIM(RC[-1])&""00000"",5)"
rResult.Offset(0, 1).Formula2R1C1 = "=MID(TRIM(RC[-2])&""000000000"",6,4)"
' We don't know if auto-recalculation mode is on now
' Application.Calculation = xlAutomatic
ActiveSheet.Calculate
Set rResult = rResult.Resize(, 2)
' Set the text format for the cells of the result
' to prevent conversions "00123" to "123"
rResult.NumberFormat = "#"
' Replace formulas with their values
rResult.Value = rResult.Value
End Sub

Excel - VBA - Search for a specific value within a cell

Is it possible to search for a specific value in a column?
I want to be able to search all of the cells in column "B" and look for the 'word' "pip" in it (without being case sensitive). I've got everything else, just need to know if this is possible or how it can be done.
My Current code looks as follows:
Sub A()
ActiveSheet.Name = "Data"
Dim ws As Worksheet
Set ws = Sheets("Data")
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Sheets.Add(After:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws1.Name = "pip"
ws.Activate
Row = 2
Dim i As Integer
For i = 1 To 10
If (Cells(i, 2).Value = (HAS pip IN IT) Then 'This is the part that i'm struggling with
Copied = ws.Range(Cells(i, 1), Cells(i, 17)).Value 'If possible, this would cut and paste so it deleted the original
ws1.Activate
ws1.Range(Cells(Row, 1), Cells(Row, 17)).Value = Copied
Row = Row + 1
ws.Activate
End If
Next i
End Sub
Edit: Just to clarify, the value in column B will never just be "pip". It will be a full sentence but if it contains "pip" then i would like the IF function to work.
Find and FindNext work nicely (and quickly!)
'...
Dim copyRange As Range
Dim firstAddress As String
Set copyRange = ws.Range("B1:B1500").Find("pip", , , xlPart)
If Not copyRange Is Nothing Then
firstAddress = copyRange.Address
Do
ws2.Range(Cells(Row, 1), Cells(Row, 17)).Value = Intersect(copyRange.EntireRow, ws.Columns("A:Q")).Value
Row = Row + 1
Set copyRange = Range("B1:B10").FindNext(copyRange)
Loop While copyRange.Address <> firstAddress
End If
'...

VBA Excel - deleting rows at specific intervals

I am new to this forum, so bear with me.
I have a CSV-file that I need to apply some VBA-modules to in order to get the information I need.
In short, I have 3 macros that together to the following:
Create a new row every 20th row
Take the number from the cell above (column A) and fill the blank space in the new row with this number.
Sum the numbers in column H from the 20 rows before the new row to get a total score. This is done subsequently for as long as new rows appear (every 20th row).
Is it possible to get these three macros in a single macro? This would make it easier to hand down to others that may need to use these macros.
Current code:
' Step 1
Sub Insert20_v2()
Dim rng As Range
Set rng = Range("H2")
While rng.Value <> ""
rng.Offset(20).Resize(1).EntireRow.Insert
Set rng = rng.Offset(21)
Wend
End Sub
' Step 2
Sub FillBlanks()
Columns("A:A").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.FormulaR1C1 = "=R[-1]C"
End Sub
' Step 3
Sub AutoSum()
Const SourceRange = "H"
Dim NumRange As Range, formulaCell As Range
Dim SumAddr As String
Dim c As Long
For Each NumRange In Columns(SourceRange).SpecialCells(xlConstants, xlNumbers).Areas
SumAddr = NumRange.Address(False, False)
Set formulaCell = NumRange.Offset(NumRange.Count, 0).Resize(1, 1)
formulaCell.Formula = "=SUM(" & SumAddr & ")"
'change formatting to your liking:
formulaCell.Font.Bold = True
formulaCell.Font.Color = RGB(255, 0, 0)
c = NumRange.Count
Next NumRange
End Sub
Thank you for any help.
Best,
Helge
You can create a single Sub calling all the other subs that you have created.
Example:
Sub DoAllTasks()
Insert20_v2
FillBlanks
AutoSum
End Sub
Then you just have to create a button and assign the DoAllTasks to it or run the macro directly.
HTH ;)
That Should'nt be that hard.
Public Sub main()
'deklaration
Dim rng As Range
Const SourceRange = "H"
Dim NumRange As Range, formulaCell As Range
Dim SumAddr As String
Dim c As Long
'Loop trough all Rows
Set rng = Range("H2")
While rng.Value <> ""
rng.Offset(20).Resize(1).EntireRow.Insert
Set rng = rng.Offset(21)
Wend
'Fill the Blank Rows in A
Columns("A:A").Select
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.FormulaR1C1 = "=R[-1]C"
For Each NumRange In Columns(SourceRange).SpecialCells(xlConstants, xlNumbers).Areas
SumAddr = NumRange.Address(False, False)
Set formulaCell = NumRange.Offset(NumRange.Count, 0).Resize(1, 1)
formulaCell.Formula = "=SUM(" & SumAddr & ")"
'change formatting to your liking:
formulaCell.Font.Bold = True
formulaCell.Font.Color = RGB(255, 0, 0)
c = NumRange.Count
Next NumRange
End Sub

Resources