Suppose I am having two sheets where on sheet 1 is this kind of data (different length of information within one row):
It might be lot of text that is "wrapped" to fit in a row (decently)
But, when I try to reference the same text, or try to use some formula for instance INDEX/MATCH to get me the same text, I am failing to get proper ROW Height...so I must adjust manually sheet 2 rows to fit nicely from heights...
Is there a way in Excel to automatically make these row expansions? Without taking a manual action every time because I won't be always sure how long it will be my original text...
You could add something into the Worksheet_Change event
Private Sub Worksheet_Change(ByVal Target As Range)
Target.WrapText = True
Target.EntireRow.AutoFit
End Sub
It might get annoying if it runs after every change for every cell, so you should add more if statements to limit which cells trigger the code.
Related
I am trying to join different lists that have less than 3 values on it, there is an example
.
I was able to do it using macros, but I wanted something more automated because these lists updated quite often, is there a way of doing something like that just by using formulas? If no, is there a way of doing it using VBA but in a better way than "clicking" buttons?
Answering VBasic2008:
I am new to this intermediary/advanced excel functions. I just realized that my Macro didn't work. It does not matter where the results will be, could just be at the end of the table. I have around 20 columns.
Basically, I tried to make something that checks if the number of values in the column is below 3 and if it is it would take this list and paste on the "Group X", but I am trying to use just functions to do that, I was able to make a list with all the columns using INDEX + MOD, but it took all of the names, from AAA to the last one, and I wanted something that would take just the list with less than 3 values.
Some update:
=INDEX(IF($F$11:$J$11=3;$F$6:$J$9;"");MOD(ROW()-ROW($O$6);4)+1;INT((ROW()-ROW($O$6))/4)+1)
I was able to come up with this formula, but everything appears with some spaces.
Thanks,
Matheus
Doing this with formulas is possible, but quite advanced. Someone here will write a formula for you which you may not be able to maintain when your scenario changes.
If you already have VBA code that does what you need doing, then you can move that code to an event procedure that starts automatically when a new value is added to the columns.
The event you need is the Worksheet_Change event and it lives in the Sheet module (right-click the sheet and click "View Code". That will show the Sheet module.
In your scenario, you want to run the code when a value is changed in columns D to G, so your code must start with something like
Private Sub Worksheet_Change(ByVal Target As Range)
' run only when a value in columns D to G are changed
If Not Intersect(Target, Range("D:G")) Is Nothing Then
' your code goes here
MsgBox "You just changed a value in one of the the watched columns!"
End If
End Sub
Edit after additional requirements
If you have Office 365 with the new Dynamic Array functions, this formula approach will work.
Building on your index formula, I made a small change. You can use the modified index formula in a helper column. Then use the Filter() function on the values returned by the Index formulas.
Index formula in cell J4 and copied down to J23
=INDEX(IF($D$11:$H$11=3,$D$4:$H$7,"#"),MOD(ROW()-ROW($J$4),4)+1,INT((ROW()-ROW($J$4))/4)+1)
Filter formula in K4
=FILTER(J4:J23,(J4:J23<>"#")*(J4:J23<>0))
If I understand you correctly, try the following:
I put the formula to count the number of entries in row 2, to make it easier to add items below.
I assumed you mean three or less; and not less than three.
If you have Windows O365, you can use the following formulas: (and change the 100 to the lowest possible row)
D2: =COUNTA(D$4:D$100)
and fill right for the number of columns
I4: =FILTERXML("<t><s>" & TEXTJOIN("</s><s>",TRUE,FILTER($D$4:$G$100,$D$2:$G$2<=3)) &"</s></t>","//s")
I have an Excel cell that contains a value that is dynamic and being automatically updated throughout the day (This is done using the RTD() function that gets the data from the ThinkorSwim Trading Application) . I am trying to capture the value every minute, put it in a dynamic range and have a plot of these values being dynamically updated throughout the day; like charting a stock price dynamically minute by minute)
My proposed solution is to create a column that contains all the times in the day, minute by minute as static values and another column that captures the value from the dynamic cell at each point in time. The problem I'm facing is how to evaluate a formula at specific times.
Something like:
time value
10:31:00 Grab value from dynamic cell at 10:31:00
10:32:00 Grab value from dynamic cell at 10:32:00
..
Right now, I'm trying to learn how I can do this with Macros.
Any hint/help is appreciated.
Update: I was able to solve the problem following Mathieu's suggestion. Please see below.
I was able to solve the problem, following Mathieu's suggestion and finding the video below.
https://www.youtube.com/watch?v=svlbqdGE4ws
Here's the gist of it:
Use the following Macro code and replace the two placeholders with your Excel cell names. The destination cell will be updated based on the value of the dynamic cell every second. Right now the code gets into a loop, but that should be easy to solve. This code doesn't exactly do what I wanted to do, but shows how the content of one cell can be updated based on another cell's value at different points in time.
VBA code:
Sub timer()
Application.OnTime Now() + TimeValue("00:01:00"), "main"
End Sub
Sub main()
Range("Reference_the_Destination_Cell_Here").Value = Range("Refernce_the_Dynamic_Cell_Here").Value
timer
End Sub
Currently I am making user form on Excel VBA and using combobox.
I have range(A2:A61) named "Division" in which was included divisions of company.
When I add this data into combo row source, I put named range - Division.
But on the other hand divisions are dynamic, I mean new divisions are created during the year.
The problem is when I created new division I can see its name on Cell A62 but it doesn't include range - named division. As the result I can't see updated combobox list.
Firstly I tried to choose range as (A:A) and called it division. In this case I can see updated combobox list but the blank cells within range makes other problems for me.
Secondly I had this code and I tried to use it as Row Source for combobox but came out error.
Set Division = Worksheets("DataCMB").Range(Range("E2"), Range("E1048576").End(xlUp))
Please, help to find out the issue.
You can insert your A2:A61 as table and define as "Division" name. So when you add new data, new data will auto include into "Division"name.
The first problem you have, and some of the other answers here have, is that you are not telling your 2nd and 3rd Range calls which sheet they should reference, so in the line below you can see I have added Worksheets("DataCMB") in front of them. Without that it will use the ActiveSheet which may not be set to DataCMB, so it will be looking for a range that is on a different sheet, and not find it.
The other problem was that your .End(xlUp) was working from a single cell and not a range, so I have changed it to look at the whole column and to look down instead of up. So the line below will give you the whole range of whatever is in that column, but will not include any blanks at the bottom, nor the header.
Set Division = Worksheets("DataCMB").Range(Worksheets("DataCMB").Range("E2"), Worksheets("DataCMB").Range("E2:E1048576").End(xlDown))
Private Sub UserForm_Initialize()
Division = Range(Range("A2"), Range("A2").End(xlDown)).Address
Me.ComboBox1.RowSource = Division
End Sub
I want to be able to put a value of 1 in an excel cell when it is selected. Cells that are not selected remain blank.
ActiveCell will use the current cell that is selected then, as you can see, it assigns the value of 1 to that cell.
ActiveCell.value = 1
If you would like it to be more modular if it is perhaps occurring many times, then consider having a look at change events here, as suggested by #Tom
I really don't recommend you doing this especially if this is for monitoring your stock and so for this time and this time only I've written it to make it a bit more safer if you're actually to do this BUT I DO NOT RECOMMEND IT.
you're going to need to paste this into the worksheet module that it relates to
Private Sub Worksheet_SelectionChange(ByVal Target As Excel.Range)
If Target.Columns.Count = 1 And Target.Rows.Count = 1 And Target.Column = 2 Then
Target.Value = 1
End If
End Sub
To get to the worksheet module you need to go into the vba editor (Shortcut Alt+F11 on windows) and paste in the correct worksheet module (Notice highlighted sheet)
I warn you though this could very quickly lead to your stock levels being inaccurate as this will run whenever you click on a cell or move around a worksheet with the arrow keys. This could mess up your whole system and there will be no undo (vba wipes the undo memory)
What would be much better to do is actually monitor your exact stock levels in excel, then use a formula such as (say you keep your stock level in column c)
=IF(C1>0, B1=1, B1=0)
This would then automatically accurately represent whether it was in stock or not.
Many "advanced" (aka: VBA) excel tutorials on the web or even excel's vba help encurage us to use the
Range("B2:B10")
method (to be precise: object) for selecting cells or getting values. In the same place they often add it's totally ok to use predefined names as well:
Range("valuesabove")
On the other hand I fell in love with the incredible power of relatively defined cell names. They make it so much easier to write and handle big composite formulas, and basically to refer to nearly anything.
However, relative names don't work in the Range("valuesabove") method the way we are used to it.
Usually (when used on the worksheet) relative names are relative to the currently selected cell or to the cell in which they are used.
In VBA's Range() object this is not true. Range is relative to a WorkSheet object, by default to the ActiveSheet. But ActiveSheet is represenetd by its leftupper cell, A1. And this is what Range turns out to be relative to. And this is why absolute names ($C$23) do work with it, and relative ones ("one column to the left, two rows up") don't.
So my question is:
How can I harness the power of relative names in VBA then?
EDIT:
Realising that my question was rather unclear (thx's go to you guys commenting tirelessly) let me try to put it in a specific form and clarify terms:
IMHO on an excel worksheet it is very comfortable to use names in order to refer to cells or define calculated values by functions based on cell values.
In excel a reference to a cell can be either relative, absolute, or mixed. This is true also when creating names. Thus we can speak about absolute, relative or mixed names (in terms of referring of course).
Here an absolute name is used a couple times (created using excel's Trace Dependents function):
Name "name" = $D$2
A relative name is used a couple times here:
Name "upright24" while, e.g. cell A7 is selected = C3 (without $ signs!). But this changes constantly according to the selected cell or region. You can check it in the name manager! (Ctrl+F3)
And this is what we can consider as a mixed name:
Name "rel_serialnumber" while, e.g. cell C6 is selected = $B6. The row of which (6) changes constantly according to the selected cell or region.
The creation of a relative or a mixed name is explicitly based on the active cell at the moment of creating the name. The creation of an absolute name naturally doesn't rely on the cursor position.
Note, that
absolute names mean a dinamic offset from the referenced cell, which is one and only
relative names mean a static offset from the referenced cell, which thus changes always corresponding to the place where the name is used
mixed names mean a mixed (or half-dynamic) offset from the referenced cell, the row or column of which thus changes always corresponding to the place where the name is used while the other remains always the same (the offset in one or the other direction remains zero).
Okay, now here is the thing. I have a database-like excel sheet where I handle the rows like records and the columns as fields for properties. The user uses this thing as follows: he "selects a record" by placing the cursor in any cell of the row of the desired record. Then he presses a big command button which starts my VBA macro. This intends to open a prepared skeleton file and fill some specific cells in it (which are btw defined by absolute names) with some values (which are defined by mixed names) from the selected record.
Since Range("name") is considered ok to use in VBA (see above) I thought Range("relativename") or Range("mixedname") will work just as fine while automatically relying on the active cell.
I couldn't be worse.
Only Range("absolutename") works in the way one would expect! Explanation see above.
So I'm after a function / method / object that is possibly as comfortable to use with a "relativename" or a "mixedname" as Range("absolutename") is.
It appears you are looking for Range.Offset() http://msdn.microsoft.com/en-us/library/office/ff840060%28v=office.15%29.aspx
However you could do it as:
'Your example Range(Col_B_in_current_row) as
Range("B" & ActiveCell.Row).Select
'Your example Range("B2:B10") -> Range("valuesabove") as
Range("B2:B10").Offset(-1, 0).Select
Just seems like a relatively simple syntax already exists for this.
I think I've found a proper and compact solution. It's
Names("mixedname").RefersToRange
Not as short as Range("mixedname") would be but it is really providing the expected values.
UPDATE:
This solution is mostly unuseful if you want to copy relative-named cell values in a source workbook to relative-named cells in a dest workbook with a single codeline. This is because Names() relies on the actual position of the cursor which is depending on which workbook is currently the active one and in most cases this won't be ok for the other.
In this case the non-fixed part of the name has to be stored:
sourcerow = ActiveCell.Row
[...]
'opening a wbk, this also makes it the active one
[...]
Names("dest").RefersToRange = mysheet.Cells(sourcerow, mybook.Names("src").RefersToRange.Column)
To reference a Range relative to another Range you can use this syntax:
myRange.Range("namedRange")
Note: This only works if both the Row offset AND the Column offsets are positive. For example if the "Refers to" formula for the named range is "=Offset(A1,r,c)", then the above syntax will throw an error if Either r Or c is negative. But, it will work if both are positive.
The asymmetry is unfortunate but business as usual for VBA...
To Reference the third column in the row of the current ActiveCell:
ActiveCell.EntireRow.Range("C1")
To reference a cell offset by (for example) 1 row and 3 columns relative to the ActiveCell:
ActiveCell.Range("C2")
Obviously, you can use the same syntax with the Selection Object or any other Range value in VBA.
Private Sub Worksheet_Change(ByVal Target as Range)
If Not Intersect(Target.Address,ThisWorkbook.Sheets('sheetname).Range('RangeName)) Is Nothing Then _
'Do whatever you want down here.
ThisWorbook.Sheets('sheetname).Range('RangeName).Offset(0,Target.Row)
End If
End Sub
This should send you on the right path to what you want (which is super unclear). Use the worksheet change event to bring in user worksheet selections and changes into VBA modules. Put it into the relevant sheet.
I had the same problem, but I did get it to work - sort of. I don't know what is different about the simple example below, but it works. At first I thought selection mattered, but no - it works without changing the active cell.
(I still can't get it to work in my main spreadsheet.)
Named range: "TestName" = Sheet1!$H1
Values in H1:H10 = 1,2,3,4,5,6,7,8,9,10
Sub Test()
Dim x As Integer
For x = 0 To 10
Range("A1").Offset(x, 0).Value = Range("A1").Offset(x, 0).Range("Testname").Value
Next x
End Sub
Result: A1:A10 = 1,2,3,4,5,6,7,8,9,10