Let's say I have three sheets in Excel. Sheet 1 is the Master sheet, sheets 2 and 3 contain different sets of information with the same headers that feed into the table in the master sheet. Is there a way to make it such that I could edit information in sheet 1 and sheet 2 will change AND vice versa so I can edit info in sheet 2 that will update the master sheet?
You could solve it by having Vlookup-formulas in your Master sheet. That way, if you change anything in sheet 2 and 3 the Master will automatically be updated.
If the user changes anything in the Master sheet, you will have to build logic in VBA on that. One way to go is to format the Master sheet so that there is something that helps the VBA know what the formula should be in the edited cell, and also to know from where the data should come. Loosely one could set up the Master sheet like this:
Row 1 is hidden and contains the template formulas
Row 2 is hidden and is completely empty (this will make less problems with filtering)
Row 3 contains headers
Row 4 and down contains the data, using the formulas define in row 1
Add the Change event on the Master sheet, that sees if the changed cell was one with a formula. If so, it will examine the template formula to identify from where the data should come. Then it will update that cell in Sheet 2 or 3 with the new value that is entered in the Master sheet. After this, it will overwrite the value manually entered in the Master sheet with the formula from the template row.
The big job here is to write a parser that understands from which cell the vlookup will get it's value.
One thing that I overlooked is that the CHANGE event is triggered only ONCE if the user pastes several cells in one go. The TARGET will then contain several rows or columns.
So this is some kind of skeleton using the above idea...
Option Explicit
Dim ChangeEventDisabled As Boolean 'Flag for disabling the Change event
Public Sub Disable_ChangeEvent()
ChangeEventDisabled = True
End Sub
Public Sub Enable_ChangeEvent()
ChangeEventDisabled = False
End Sub
Sub Worksheet_Change(ByVal Target As Range)
Dim updatedValue As Variant
Dim SourceCell As Range
'While the MasterSHeet is populated intially, we don't want this event to do anything
If ChangeEventDisabled Then
'There are chenges being done in teh sheet that should not trigger updates of the source-sheets.
Else
'Only run the code if it was a data-cell that was changed
If Target.Row > 3 Then
'We are in the rows containg data
'Did the changed cell contain a Vlookup formula before the user changed the cells value?
If UCase(Cells(1, Target.Column).Formula) Like "=VLOOKUP(*" Then
'A vlookup normally populates this cell.
'To know from where the data normally comes, I will need to put back the formula in the changed cell.
'So, first save the new value that we will write in the source cell
updatedValue = Target.Value
'Insert the formula again in the cell
'As we will now CHANGE a cell in the Masterr sheet, a Change event will trigger. Disable it temporarily
Disable_ChangeEvent
Cells(1, Target.Column).Copy Destination:=Target
Enable_ChangeEvent
'Find out from which cell the data is being fetched by the Vlookup
Set SourceCell = MyMagicParsing(Target)
'Update the source-cell with the new value
SourceCell.Value = updatedValue
End If
End If
End If
End Sub
Function GetSourceCell(Target As Range) As Range
'This function should decipher the formula in the cell Target, and figure out from where
'the data is actually coming. It shoudl return the range which is the source of the data.
'As I dont know how to do that quickly, I just hardcode the cell that is the source.
GetSourceCell = Worksheets("Sheet2").Cells(67, 3)
End Function
Related
I'm new to excel but now i'm stuck at something.
The one thing i try to achieve is that if i add a specific word into a textbox, another cell gets +1 (so if 0 and text has been entered in the textbox, it changes to 1 etc.)
so for example:
Cell B2 = Apple
Cell H2 : value of B2
I'd like to get, if possible, one or two textboxes where i could put the type of product and another box for the amount.
Thanks in advance.
OK. Here's a solution.
Set up a named range. I entered 5 different fruit in one column and 5 different quantities in the adjacent column (doesn't matter where but must be adjacent). I named the range "Products" but any other name will do just as well.
I set up a data validation list. I used cell G3 but any other will be equally suitable. I pointed the data validation list to =INDEX(Products,0,1), meaning the first column of the Products range.
Now I added code to the worksheet. This code must be in the code sheet of the worksheet on which G3 is located. That code sheet will have a name like Sheet1 (Sheet1). Don't use a standard code module with a name like Module1. Here is the code.
Private Sub Worksheet_Change(ByVal Target As Range)
' 018
Const Trigger = "G3" ' change to suit
Dim Qty As Long
With Target
If .Address = Range(Trigger).Address Then
On Error Resume Next ' in case not found
Qty = Application.VLookup(.Value, Range("Products"), 2, False)
.Offset(0, 1).Value = Qty + 1
End If
End With
End Sub
Note that the Trigger cell is named as "G3". This must be the cell where you have the data validation drop-down.
This code will run whenever Trigger is changed. You make a selection there and the VLOOKUP function will find the quantity in column 2 of the Products range. If the item isn't found in the list it will return 0 but you can set the cell validation to prevent the entry of an item that isn't in the list. The code will add one to the quantity found and issue the result in .Offset(0, 1), meaning one column to the right of the Trigger cell.
You might want to do other things with your idea. I think the system I suggest can be adapted to whatever you have in mind, including changing the quantity in the Products list.
I tried looking at other similiar questions and solutions but as an Excel beginner I couldn't quite figure it out.
So I have the following macro:
Sub Worksheet_Change(ByVal Target As Range)
Dim wsNew As Worksheet
If Target.Cells.Count > 1 Or IsEmpty(Target) Then Exit Sub
On Error Resume Next
If Not Intersect(Target, Range("B46:B99")) Is Nothing Then
ThisWorkbook.Sheets("LT").Copy _
After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
End If
End Sub
It opens a new sheet in the same workbook and I'd need to auto populate certain cells with data from the main sheet. Main sheet: http://i.imgur.com/RJe44hQ.jpg new sheet: http://i.imgur.com/eatbg6j.jpg . The cells I need copied are in red.
Thanks in advance for any help! Really new to all this..
Since you don't specify which value(s) you need to pull from the main sheet I can't get too specific, but in general there are three approaches to take.
1) If the data is in contiguous range(s) of cells on both sheets, you can just copy the data from the main sheet after creating the new sheet, and then paste the values to the correct target range
2) If the data isn't contiguous on both sheets, then your next best option would be to have the value for each target cell set based on the value of the corresponding cell on the main page. Ex: To set A2 on Sheet2 to the value of B4 on Sheet1 you would use Worksheets("Sheet2").Range("A2").value = Worksheets("Sheet1").Range("B4").value
3) This one also works if the data isn't contiguous, but gets to be troublesome if there are more than ~5 values to copy. You can create an appropriate variable (string for text, long/int for numbers, etc.), set that before creating the new sheet, and then use them to set the appropriate cells once the new sheet is created.
I've an excel worksheet which comprises of many sheet in turn let say around 5...I want to write a macro which will identify the presence of color say red in excel sheets Sheet2, Sheet3, Sheet4 and Sheet5 if there is any red color in any of the cell, it will report the sheet name in Sheet 1 of the workbook that Sheet<> so and so contains the red color in its any one of the cell.
Till yet i was only in position to identify that whether there is red color present in the particular sheet...but don't know how to report the corresponding sheet name in the sheet 1.
Sub CheckColor()
Dim Row
For Row = 2 To tsheet.UsedRange.Rows.Count
For chkcol = 1 To Sheet1.UsedRange.Columns.Count
If tsheet.Cells(Row, chkcol).Interior.ColorIndex = 3 Then
'How to report the corresponding sheet name in sheet 1???
End If
Next
Next Row
End Sub
First, I think using Range.Find() along with FindFormat would be much more efficient:
Private Sub test()
Application.FindFormat.Clear
Application.FindFormat.Interior.ColorIndex = 3
Range("A1:C3").Find(What:="", LookAt:=xlPart, SearchFormat:=True).Value = "test"
End Sub
For your principal question, I think you first need to establish whether you want to execute the code for all sheets or for a subset. If it's for all sheets, then you can simply wrap up the code above inside a for each loop on the Worksheets collection.
If you need to execute this code for a subset of the worksheets, then you can either use a rule (first 4 characters = "abcd") or hard code them in an array.
Then, it's just a matter of checking that the range returned by Find() is not nothing which means success. If the condition is met, then the current sheet is to be used by the main sheet as you want it.
Scenario: I can't post the actual workbook due to sensitive materials but I'll explain it as best as possible.
Each Sheet is divided into branches i.e.: Sheet2 is Branch 2, Sheet3 is Branch 3 and so on.
For each sheet the column are the same.
Column A has the branch number in it.
Column B has irrelevant information so i just hide that column.
Column C has a system number (specific to each account.
Intention: I want to create another sheet called CallOuts.
I want to copy some rows (from various branches) and paste them onto the 'Master sheet' (CallOuts) I can work on the CallOuts sheet instead of going to each branch. So that whenever I edit a cell it will also update/change that exact same cell in the branch sheet and vise versa with the master sheet.
Problem: I know MS Exccel has a "Paste Special" function where it adds the cell. The problem with that is it links the cell# so if I sort the Master sheet it will replace the row into the wrong branch sheet.
E.g.: If System# J112 is in branch 2 sheet, row 2 and I have the link pasted in Row 4 in the master sheet, if I make updates on the Master sheet and then re-sort it and the System# now moves to Row 2 (on the master sheet) whatever is in Row 4(on the master) will now be in Row 2, Branch 2 sheet.
I was thinking maybe a macro where I could copy and paste the entire row from the master sheet. Do some type of case selection to check which branch is in column A and then find the same system # on the branch sheet then paste the whole row.
My VBA level is novice at best so any help would be appreciated.
OK, So I saw your attempt below. I am not sure how your code works but it seems like you were on the right track. However, I don't think the Case syntax is appropriate for this situation. You simply need a macro that will read what is in your "CallOuts" sheet and use that data to update your individual branch sheets. This macro should work for you:
Sub UpdateRecordsFromMasterSheet()
Dim wksht As Worksheet
Dim wkb As Workbook
Dim row As Range
Dim Row_to_Update As Range
Dim sysnum As Variant
Set wbk = ThisWorkbook
Application.ScreenUpdating = False
For Each row In Sheets("CallOuts").UsedRange.Rows
row.EntireRow.Copy
sysnum = row.Cells(1, 3).Value
For Each wksht In ActiveWorkbook.Worksheets
For Each Row_to_Update In wksht.UsedRange.Rows
If Row_to_Update.Cells(1, 3).Value = sysnum Then
Row_to_Update.PasteSpecial
End If
Next Row_to_Update
Next wksht
Next row
Application.ScreenUpdating = True
End Sub
This assumes you have your system number in column "C". So here is what I am imagining: Each time you assign an employee a bunch of rows - your employee updates those rows - and then you paste that data back into the "CallOuts" sheet. Then you run this macro and it will update the individual branch sheets based on what is in the "CallOuts" sheet.
If your a visual person here is how it will look:
Here is the updated callouts sheet:
Here is how the branches will look before the macro:
Here is the updated branch after the macro runs:
Try it out and let me know how it works. Note: this is just a start to show you how to do something like this - you could make this process more efficient by having the macro loop through the actual workbooks that the employees submit to you so you wouldn't have to copy and paste the data into your "CallOuts" sheet every time. Good Luck.
I need Help!
I am not well versed in VBA or Macros but i cannot find any other way to accomplish what i need to do without using it.
I have a sheet which i will be using to track Purchase orders, and what i need to do is; when i have a row in sheet 1 (Purchase Orders) which has been recieved i.e. the date of receipt has been recorded in column H i need for the entire row to be cut and pasted into sheet 2 (Received orders).
The header takes up the first 7 rows the rows, so i need the macro to look at rows 8-54. Once the received items are removed from sheet 1, i need the row to also be deleted or preferably for the list to be sorted by column A moving the now empty row which has been cut from open for a future entry.
Any help would be greatly appreciated.
The "Record Macro" feature should be enough to do the task you describe.. In Excel 2007, go to the Developer tab in the Ribbon, and select "Record Macro", and perform exactly the steps you are describing. It will record the equivalent VBA code, which you can then execute - or tweak/modify.
I tested this out, here's one way to do it:
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Dim receivedDate As Range, nextOpen As Range, isect As Range
Set receivedDate = Sheet1.Range("H8:H54")
Set isect = Application.Intersect(Target, receivedDate)
If Not (isect Is Nothing) And IsDate(Target) = True Then
Set nextOpen = Sheet2.Range("A1").End(xlDown).Offset(1, 0)
Target.EntireRow.Copy Destination:=nextOpen.EntireRow
Target.EntireRow.Delete
End If
Application.EnableEvents = True
End Sub
This would be pasted into the Sheet1 code. Any time a cell is changed on sheet1, the code checks to see if it's in the critical range that you specified. (H8:H54) If it is, it then checks to see if it's a date. If it is, it then copies the entire row, puts it in the next open row on Sheet2, and deletes the original row. The cells below it will get shifted up so there are no gaps.
Since the code functions on a cell changing event, it disables "Application.EnableEvents" in order to avoid a loop of changing a cell to call an event which changes a cell to call an event... etc.