Excel/VBA/SQL Grab value from one row and update in another - excel

What I'm trying to do is update amount from one line to another in Excel. They don't have any key that combines but they are in pattern. Always start with Item Group and about 3-7 lines after is End of Item Group. I want to grab the amount from End of Item Group and update the line in Item Group but always Item Group will be first then End of Item Group.
I could upload to SQL if it's easier to work on or Access.
This is the problem.
This is what I'm trying to accomplish:
After this update I wanted to delete every line after item group but only up to end of item group.

So basically if you don't already have the Developer tab, you would need to go to Options > Customize Ribbon > Click 'Developer'
Then click on VB Editor on Developer tab and right click in project area and select "insert new module". In the new module insert this code and save.
To make it easy to run, you can go to Developer tab > Insert > Button. Then right-click on the button and assign it to this macro you just created so everytime you want to update the item group values you can click the button. If the button doesn't let you "assign a macro" then you probably inserted the wrong type of button.
Option Explicit
Sub UpdateValues()
Dim itemCol As Long
Dim lastRow As Long
Dim row As Long
Dim lastEnd As Double: lastEnd = 0.0
' set reference to your worksheet
With ThisWorkbook.Worksheets("your sheet name")
' set column with title 'Item_Type' in Row 1
For row = 1 To 20
If Trim(CStr(.Cells(1, i).Value)) = "Item_Type" Then itemCol = i
Next
' find last row of Item_Type column
lastRow = .Cells(.Rows.Count, itemCol).End(xlUp).Row
' loop backwards thru rows
For row = lastRow To 1 Step -1
' if cell contains word 'end'
If InStr(LCase(CStr(.Cells(row, itemCol).Value)), "end") Then
' set our group value
lastEnd = .Cells(row, itemCol+1).Value
' if lowercase(cell) = 'item group'
ElseIf LCase(CStr(.Cells(row, itemCol).Value)) = "item group" Then
' put end value in the cell
.Cells(row, itemCol+1).Value = lastEnd
End If
Next row
End With
End Sub

Related

Excel checkbox change row background color

i create some table, and make a datestamp when i enter data
in column "A" the date is shown in column "E" , so i know when data is entered.
I put checkbox in column "F", but I need help with next:
When checkbox is checked the date must be written in column "G"
The background from "A to D" (but only in this row) must be changed to red color
The data from A, B and C must be copied to another sheet also in A,B and C
I hope someone will help me because i stuck :(
I also attack a screenshot.
Thanks in advance
The procedures will help you get the macro operational, ensure you try the code on a copy of your workbook
Add a command button (ActiveX control) and paste the macro
Note: You need to ensure that you place the Command Button in the worksheet where you have your check boxes.
Step 1:
Copy the “LoopCkBoxesAddDateStampClrCelsCopy()” macro
Sub LoopCkBoxesAddDateStampClrCelsCopy()
Dim lRow As Long
Dim CkBx As OLEObject
'For/Next loop cycles through all checkboxes in worksheet
For Each CkBx In ActiveSheet.OLEObjects
lRow = Sheet2.Cells(Rows.Count, 1).End(xlUp).Row
'If the checkbox is checked then accomplish the lines of code between the If/End If
'The part after the "And" ensures that if a date is in the cell it will not be over written
If CkBx.Object.Value = True And CkBx.TopLeftCell.Offset(, 1).Value = "" Then
'Next line of code puts the date in first cell to left of the checkbox
CkBx.TopLeftCell.Offset(, 1).Value = Format(Date, "mm-dd-yyyy")
'Next line of code colors the first 4 cells in checkboxs' row
CkBx.TopLeftCell.Offset(, -5).Resize(, 4).Interior.Color = vbRed
'Next line of code copies the first 3 cell in the checkbox row to the first empty row on sheet 2
Sheet2.Cells(lRow, 1).Offset(1).Resize(, 3).Value2 = CkBx.TopLeftCell.Offset(, -5).Resize(, 3).Value2
End If
Next CkBx 'loops to the next checkbox
End Sub
Note: If you plan on pasting your cells to a different worksheet, please change both Sheet2s in the code.
Step 2:
On the Developer tab, in the Controls group, click Insert, and then under ActiveX Controls, click the Command Button.
Step 3:
Click the worksheet location where you want the command button to appear.
Step 4:
Right click the button, click View Code. This will launch the Visual Basic Editor.
Step 5:
In the VBE, highlight the Private Sub CommandButton1_Click() and the End Sub, and Paste the macro
Step 6:
Close the Visual Basic Editor, and click Design Mode Button image to ensure design mode is off.
Step 7:
Select the checkboxes in your worksheet and click the button to run the macro

Excel VBA TopLeftCell.Row property inconsistent results

Here's the scenario. When a row is inserted in the worksheet there's a worksheet_change event that calls a sub that inserts five pairs of buttons on the row that was inserted. When one of those buttons is clicked it runs a sub that issues a MsgBox that displays the TopLeftCell.Row and Column of the button. Multiple rows can be inserted, each with its five sets of buttons (ten in total). Any button in any row can be selected at any time.
What I'm seeing is that after I open the workbook and press one of the buttons, the MsgBox always displays the correct column, but it seems to get "stuck” on one particular row no matter which row the button that I'm clicking is actually in. If I delete the row it is stuck on then it gets "stuck" on a different row (as long as it also contains buttons). But not all of the buttons will be stuck to the same row.
If I copy two adjacent rows with buttons that are “stuck” on the same row to another location, those buttons are still stuck together except on a different row.
It seems like there’s a problem with the button collection. If I save the workbook the problem goes away. If I insert a new row and the Add_Buttons routine runs again, the problem reappears but involving different rows. So my button routine is probably leaving something temporary behind that gets cleared up when I do a save.
Here's the code that builds the buttons.
Public activeWS As Worksheet
Public activeRG As Range
Public Sub Add_Buttons(ByVal myRow As Long)
'Add the five sets of Submit IM and Submit Webins buttons to a new row. The code
'uses named ranges to locate the cells where the buttons should be added so that
'new columns can be added to the spreadsheet without requiring changes to the code.
'The headings must be labeled 'IM#' and 'Webins#'.
Dim i As Long
Dim t As Range
Dim btn As Button
'In each range, place the button below the column label.
Application.ScreenUpdating = False
For i = 1 To 5
Set activeWS = Sheet1
Set activeRG = activeWS.Range("Scan" & i & "_Hdngs")
'The start of the range plus the position of the specified column in
'the range gives the absolute column location to add the button
'Create the Submit IM button
nCol = activeRG.Cells(1, 1).Column + findCol("IM#", activeRG) - 1
Set t = activeWS.Range(Cells(myRow, nCol), Cells(myRow, nCol))
Set btn = activeWS.Buttons.Add(t.Left, t.Top, t.Width, t.Height)
With btn
.OnAction = "Create_Primary_IM"
.Caption = "Submit IM"
.Name = "BtnIM" & myRow & i
.Font.Size = 10
End With
'Create the Submit Webins button
nCol = activeRG.Cells(1, 1).Column + findCol("Webins#", activeRG) - 1
Set t = activeWS.Range(Cells(myRow, nCol), Cells(myRow, nCol))
Set btn = activeWS.Buttons.Add(t.Left, t.Top, t.Width, t.Height)
With btn
.OnAction = "Create_Primary_WAS"
.Caption = "Submit Webins"
.Name = "BtnWAS" & myRow & i
.Font.Size = 10
End With
Next i
Application.ScreenUpdating = True
End Sub
Here's the code executed by the buttons:
Public Sub Create_Primary_IM()
MsgBox ("Row, Col of pressed button: " & ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row _
& ", " & ActiveSheet.Shapes(Application.Caller).TopLeftCell.Column)
End Sub
Public Sub Create_Primary_WAS()
MsgBox ("Row, Col of pressed button: " & ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row _
& ", " & ActiveSheet.Shapes(Application.Caller).TopLeftCell.Column)
End Sub
Here's what I believe to be the cause of the problem, its effect on the spreadsheet, and the solution.
The cause was duplicate button names. I had been naming the buttons based on their row and column at the time of creation. The problem is that rows and their buttons could be inserted or deleted anywhere in the sheet. It's not hard to see (except that I didn't see it for a while) that it was possible to insert a row and create its buttons in the same absolute row multiple times. This resulted in buttons with the same .name property.
The effect was that when I clicked one of the duplicate buttons it found the TopLeftCell.Row of the original button with that name, not of the row that the button was actually on. When I saved the file (not closed it) and clicked the same button, it had been renamed to something like 'Button nnn' and the correct row was returned. If I saved the file and re-opened it, the duplicate button name condition was still present. So Excel was replacing duplicate names in that collection when I saved the file, but not committing those changes when I closed the file.
The quickest solution was the easiest as well. I let Excel do the naming. I don't really need the buttons to have names. All I need is the row number. Another solution would be to generate a unique name, but what's the point if that's what Excel is going to do for me anyway?

Add Conditons to Unhide column in a sheet with Mulitple Criteria

A little Help again please.
Codes below work for hiding columns that do not match B5.
Now my problem is, I want to unhide column that matches values
from B6 and B7 at the same time.
Reference Values from Command Sheet Column B Row 5,6,7.
Let B5 is MARCH
Let B6 is JANUARYsample picture
Let B7 is FEBRUARY
Sheet Name (GRA_NewGen CI) Note that All Data's per row/column are here.
Range from Sheet Name to Match B5,B6,B7 is Column C Row 4 up to End of Column in row with Values.
Below is the 'Code
'Sub GRA_NewGen_CI()
Dim cell As Range
Application.ScreenUpdating = False
With Sheets("GRA_New Gen CI")
For Each cell In .Range("C4", .Range("XFD4").End(xlToLeft))
cell.EntireColumn.Hidden = cell.Value <> Sheets("Command").Range("B5") And Not IsEmpty(cell)
Next cell
End With
Application.ScreenUpdating = True
'End Sub
If all you want is to hide all rows marked "JANUARY", "FEBRUARY" etc. you will have more flexibility and faster action by using Excel's Filter functionality. Learn here about Filters.
That gave me quite a ride. All those hidden columns are tricky. But now it's your turn. Please follow the instructions.
On your 'Command' sheet, find a blank column and enter "Show All" in one of the cells and this function in the cell below that:
="Show "& B5
I prefer you to have all the 12 months in B5:B16, but if you have only Jan to Mar or prefer to change the content on the fly that is OK as well. Copy the formula down for as long as you have relevant data (month names or column captions) in column B. Give the range I just described a name. I gave it the name "DropdownList". Make sure the named range has a 'Scope' of "Workbook" (meaning, it is visible from all parts of the workbook).
Place a command button on the GRA_New sheet in position A4. Perhaps you already have a button elsewhere. In that case I will ask you to play along and make another one for now. Later you can move this button to any other location, including another sheet, but not in a column to be possibly hidden. This command button will be a Validation drop-down. Enter
"Allow" = List and
"Source" =DropdownList (including the = mark.
You should now have a validation dropdown showing "Show All" in first position, "Show January" in second, and more "Show ..." depending upon the size of the named range DropdownList. Make sure that there is a single space between in "Show January" and "Show all", not more and not less, and every line consisting of 2 words, the second of which is relevant.
Now add the following procedure to the code sheet of the "GR_New ..." sheet.
Private Sub Worksheet_Change(ByVal Target As Range)
'17 Mar 2017
If Target.Address = Range("A4").Address Then
SetDisplay_GRA_NewGen Split(Target.Value)(1)
End If
End Sub
In this procedure, please change the reference to "A4" to the cell where you have the validation dropdown.
The next procedure goes into a normal code module. By default its name would be "Module1", but you can give it any name you like.
Sub SetDisplay_GRA_NewGen(ByVal Cmd As String)
' 17 Mar 2017
Dim Spike As String
Dim CountHidden As Integer
Dim FirstColumn As Long, LastColumn As Long
Dim CapRow As Long, Cap As String
Dim C As Long
CapRow = 4
FirstColumn = 3 ' = column C
With Worksheets("GRA_New_Gen_CI")
LastColumn = .UsedRange.Columns.Count
If StrComp(Cmd, "all", vbTextCompare) Then
With Range("DropdownList")
For C = 2 To .Rows.Count
Cap = Split(.Cells(C).Value)(1)
Spike = Spike & "|" & Cap
Next C
End With
For C = FirstColumn To LastColumn ' count hidden columns
Cap = .Cells(CapRow, C).Value
If .Columns(C).Hidden Then
If .Columns(C).Hidden Or InStr(1, Spike, Cap, vbTextCompare) = 0 Then
' if Cap can't be selected it is counted as not hidden
CountHidden = CountHidden + 1
End If
End If
Next C
Application.ScreenUpdating = False
If CountHidden = 0 Then
' hide all except the specified column
.Range(.Columns(FirstColumn), .Columns(LastColumn)).Hidden = True
End If
For C = FirstColumn To LastColumn
With .Columns(C)
If .Hidden Then
Cap = .Cells(CapRow).Value
If StrComp(Cap, Cmd, vbTextCompare) = 0 Then .Hidden = False
End If
End With
Next C
Else
.Range(.Columns(FirstColumn), .Columns(LastColumn)).Hidden = False
End If
End With
Application.ScreenUpdating = True
End Sub
Look for the two declarations in this procedure:
CapRow = 4
FirstColumn = 3
Row 4 is the row on your data sheet in which the program will look for the months names. Column 3 (= "C") will be the first column in which the program will expect to find a month's name. Columns A:B will never be touched.
Now your system is ready. You will need to know how to operate it.
1. When you select "Show All" from the dropdown all columns starting from FirstColumn will be shown. Call this a reset.
2. When you select any of the items from the dropdown columns with that name in CapRow will be shown.
3. When you select another month it will be added to the one already shown.
4. When all columns are shown already, only the selected one will be displayed.
You can modify the range DropdownList anytime, make it longer or shorter. The important thing is that the names in the dropdown are available in the CapRow. The program compares them as text, meaning "show all" is the same as "SHOW ALL".

Button Generates the columns from user input but not the cell lines?

I implemented a button that ask the user where to add a column, and the button takes the user input(A-Z) and generates the column until the end of the table NOT SPREADSHEET. The column ends based on how many rows there are in my table, meaning if there are 10 rows, after the user clicks the button an inputs where they want the column to be(They input a letter of the column A-Z), I should not see a column box on line 11 of the spreadsheet.
Now I've managed to do this my issue is below:
My issue is the cells the button generate does not include the lines or boxes around the cells so that you are aware that its an extension of the table?
here is what I mean: Picture of spreadsheet
notice the i column there are no lines around the cells?
Here is code, I think I am missing a copy function after the line
shift:=xlRight, but I don't know how to implement it?
I don't want to use macros because since the tables rows and column change due to the user's input I will have to constantly hard-code the range into the macro which i dont want.
Trust me I tried it an its annoying.
Private Sub CommandButton2_Click()
Dim x As Variant
Dim ColumnNum
x = InputBox("Enter a column that you want to add: ", "What column?")
If x = "" Then Exit Sub
ColumnNum = x
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum).Insert shift:=xlRight
ThisWorkbook.Sheets("Sheet1").Columns(ColumnNum).ClearContents
End Sub
you could try this:
Private Sub CommandButton2_Click()
Dim colIndex As Variant
colIndex = Application.InputBox("Enter a column that you want to add: ", "What column?", , , , , , 2) '<--| force a text
If colIndex = "" Then Exit Sub
With ThisWorkbook.Sheets("Sheet1").Columns(colIndex) '<--| reference column you want to insert
.Insert shift:=xlRight '<--| insert a new column , then the referenced one shifts one column to the right of the inserted one
.Offset(, -2).Copy '<--| copy the column two columns to the left of the referenced one (i.e. one column left of the new one)
.Offset(, -1).PasteSpecial xlPasteFormats '<--| paste formats to the new column
Application.CutCopyMode = False
End With
End Sub

Select value from dropdown box but populate hidden column

I have a set of unique IDs and names:
ID NAME
aa Jeff
bb Matt
cc Trung
dd Trung
All IDs are unique. Names are not.
On a worksheet I have a series of columns:
Date Time ID Name Value
1/1 1:30 aa Jeff 123124
1/2 2:20 cc Trung 12443234
Right now, a user will populate the ID field, the vlookup will return Name.
Is there a way to set up a dropdown on the ID cell that shows a concatenation of the ID and Name, but when selected, stores only the ID?
The idea is that the concatenated value that appears in the dropdown (Ex: aa | Jeff) is more user-friendly that just "aa".
Well, hope my answer will help. If not, please tell me and I will try to improve it.
The code is inside the Worksheet
Private Sub ComboBox1_Change()
'Just use the frist part of the string, ID
Range("I1").Value = Split(Me.ComboBox1.Value, " | ")
'Optional, if you want to put the name using code.
'If not, just use the VLOOLUP
Range("J2").Value = Split(Me.ComboBox1.Value, " | ")(1)
End Sub
Private Sub Worksheet_Activate()
Dim r
Dim c
Dim i
Dim L
Dim myRngID As Range
r = Range("C2").End(xlDown).Row 'the final row of the ID column
c = Range("D2").Column ' the number of the column of the name
Set myRngID = Range(Cells(2, 3), Cells(r, 3)) 'use only the ID range
'Just to clean the ComboBox everytime to avoid duplicates
Me.ComboBox1.Value = ""
L = Me.ComboBox1.ListCount
On Error Resume Next
For i = 0 To L
With Me.ComboBox1
.RemoveItem i
End With
Next i
On Error GoTo 0
'Pupulate the ComboBox with the string {ID[space]|[space]NAME}
For Each i In myRngID
With Me.ComboBox1
.AddItem i.Value & " | " & i.Offset(0, 1).Value
End With
Next i
End Sub
In the worksheet just this
As you can see, the only formula in the sheet is in J1, the VlookUp. In J2 the name is inserted using VBA.
The ComboBox has any special property. Everything is in the code above.
The result is that the name is always taken from the ComboBox, and then no matter which one is selected, always will be the right one, as in the VlookUp.
This should work
Select the Cell on the Second Sheet (the one that will be the vlookup)
Go to the Data Tab > Data Validation > Data Validation
On Settings Select List > Click Source button at the right of the input box > Select Range from the first workbook Screenshot
Now copy and paste that cell in the column on the second workbook

Resources