Exceeding Max Char Limit in Excel - excel

How do I use more than 255 characters in Excel's CONCATENATE function? I am actually also using the CONCATENATE function within the HYPERLINK function in EXCEL. An example looks like this:
=HYPERLINK(CONCATENATE("http://www.google/com/morethan255charsmorethan255charsmorethan255charsmorethan255charsmorethan255charsmorethan255charsmorethan255charsmorethan255charsmorethan255charsmorethan255chars","morethan255chars morethan255charsmorethan255charsmorethan255charsmorethan25"),"link");
UPDATE: It's not issue with CONCATENATE function, but an issue with the first parameter of the HYPERLINK function. Using a string longer than 255 characters directly/indirectly (ex: =HYPERLINK(K204,"link") where K204 contains the 256-character length link) fails the HYPERLINK function
I realize that I can use a URL shortener, but I am doing this for ALOT of links which would require ALOT of manual use of the URL shortener.

UPDATE: Because of Karls comment I revisited my answer an found out, that Excel 2007 does not seem to allow User Defined Functions to set hyperlinks anymore (quite sensibly, see my own comment in the code). So the original code (below the line) does not work in more recent versions of Excel (I haven't tested Excel 2010 but I assume the result is the same). For historical reasons I do not delete the old code (an editor might think otherwise -- feel free to edit/ delete accordingly).
So what remains is to set long hyperlinks programatically, e.g.
Sub insertVeryLongHyperlink()
Dim curCell As Range
Dim longHyperlink As String
Set curCell = Range("A1") ' or use any cell-reference
longHyperlink = "http://www.veryLongURL.com/abcde" ' Or a Cell reference like [C1]
curCell.Hyperlinks.Add Anchor:=curCell, _
Address:=longHyperlink, _
SubAddress:="", _
ScreenTip:=" - Click here to follow the hyperlink", _
TextToDisplay:="Long Hyperlink"
End Sub
What follows does not work in Excel 2010 anymore; see my comment above
The "copy the hyperlink from Word and paste into Excel" got me thinking. So obviously the limit is both in the built-in HYPERLINK-function and in the dialog-window 'edit hyperlink'. On the other hand it should be -- and actually is -- possible to set longer hyperlinks via VBA.
This code does not work in Excel 2010 anymore
Function myHyperlink(cell As Range, _
hyperlinkAddress As String, _
Optional TextToDisplay As Variant, _
Optional ScreenTip As Variant)
' Inserts a Hyperlink
' at the position cell (this should be the position where the UDF is used,
' since the return value of the UDF is = TextToDisplay)
' with the hyperlinkAddress
' optional TextToDisplay
' optional ScreenTip
' #######################################
' Warning Warning Warning Warning Warning
' #######################################
' 1) Since it is really bad practice to have a function perform procedural
' tasks, you should not do this.
' 2) You have no garantee, the link is updated when the value hyperlinkAddress changes
' USE AT YOUR ONE RISK AND ONLY IN CASE OF EMERGENCIES :-)
' If more than one cell is selected as target range,
' use the top left cell
Set cell = cell.Resize(1, 1)
If IsMissing(TextToDisplay) Then
TextToDisplay = hyperlinkAddress
End If
If IsMissing(ScreenTip) Then
ScreenTip = hyperlinkAddress & " - Click here to follow the hyperlink"
End If
cell.Hyperlinks.Add Anchor:=ActiveCell, _
Address:=hyperlinkAddress, _
SubAddress:="", _
ScreenTip:=ScreenTip, _
TextToDisplay:=TextToDisplay
' There doesn't seem to be another way to set TextToDisplay
myHyperlink = TextToDisplay
End Function
Use as a normal Excel-function, but be sure to add the current cell as first parameter (i.e. the following formula is inserted in cell A1)
=myHyperlink(A1,B1)
=myHyperlink(A1,B1,"TextToDisplay", "ScreenTip")
You can neither pull the formula down nor copy it to another cell. If you do that you have to let the formula be recalculated (neither ALT-CTRL-F9 nor ALT-CTRL-SHIFT-F9 as force recalculate seem to work) so go into each cell, press F2 to activate it and finish with Return.
I hope I am not helping you to screw up too many Excel-Workbooks.
It is probably safer to write an VBA that is explicitly started that iterates through a list and writes to hyperlinks. That way they can reused and there are no functions.
Regards
Andreas

I have Excel 2007 and I tried making a cell with 300 characters in A1, and another with 300 different characters in B1.
Then I made C1 = CONCATENATE(A1, B1).
I can see all of the characters from both cells. Nothing is missing or truncated and no errors were received. It looks good to me.
What makes you think that the concatenate is failing? Are you having trouble seeing your results? If your cell contains more than 1,024 characters only the first 1,024 are displayed in the cell. However they are still there and if you copy and paste them all of the characters will be copied.
Edit:
Now that you have editted your question I realize the problem is with HYPERLINK and not CONCATENATE.
The only way to get around the 255 character limit of HYPERLINK formula in Excel is to copy a hyperlink from Word and paste it into a cell in Excel. Then it can be super long. I know this is an unreasonable manual process if you have a lot of links but it seems the only way to get it into an Excel spreadsheet and yet still have it be a hyperlink that you can click on and be redirected. If you don't need it to act like a hyperlink then I would suggest rewriting your queries to return the hyperlink as its own text field and then it will be fine.

You might be out of luck. It seems that the character limit for hyperlinks in Excel is 256 as pointed out here. If you test it out yourself (I have Excel 2007, too), =HYPERLINK(REPT("a",255)) works and =HYPERLINK(REPT("a",256)) does not and throws a #VALUE! error.

Here's some VBA which uses bitly.com to shorten a URL. It is based on the bitly API documentation.
Create a free account on bitly.
Valid email address with bitly.
Get access token from bitly.
Substitute the access token in the VBA code below where it says MY_TOKEN.
Copy and paste the code in Excel's VBA.
In a cell, write the following '=Hyperlink(GetURL("some really long URL"))' without single quote ' marks. Note: Instead of passing a string to GetURL(), pass a reference to a cell which has a URL in it as text.
Public Function GetURL(longUrl As String) As String
Dim xml As Object
longUrl = URLEncode(longUrl)
Set xml = CreateObject("MSXML2.XMLHTTP.6.0")
xml.Open "GET", "https://api-ssl.bitly.com/v3/shorten?format=xml&access_token=MY_TOKEN=" & longUrl, False
xml.Send
GetURL = xml.responsetext
head = InStr(GetURL, "<url>") + 5
tail = InStr(GetURL, "</url>")
GetURL = Mid(GetURL, head, tail - head)
End Function
Function URLEncode(ByVal Text As String) As String
Dim i As Integer
Dim acode As Integer
Dim char As String
URLEncode = Text
For i = Len(URLEncode) To 1 Step -1
acode = Asc(Mid$(URLEncode, i, 1))
Select Case acode
Case 48 To 57, 65 To 90, 97 To 122
' don't touch alphanumeric chars
Case 32
' replace space with "+"
Mid$(URLEncode, i, 1) = "+"
Case Else
' replace punctuation chars with "%hex"
URLEncode = Left$(URLEncode, i - 1) & "%" & Hex$(acode) & Mid$(URLEncode, i + 1)
End Select
Next
End Function

Dunno if my answer is still useful but I had the same issue couple of days ago, the best way and proved way to do a workable hyperlink that exceeds a 255 char limit is to first split it, with CONCATENATE(), and use the cell with CONCATENATE() function in VBA.
For me it looks like:
A1 = LinkPart1
A2 = LinkPart2
A3 = LinkPart3
A5 = CONCATENATE( A1; A2; A3 )
VBA Code you need to link with A5:
Sub insertVeryLongHyperlink()
Dim curCell As Range
Dim longHyperlink As String
Set curCell = Range("A7") ' or use any cell-reference
longHyperlink = [A5]
curCell.Hyperlinks.Add Anchor:=curCell, _
Address:=longHyperlink, _
SubAddress:="", _
ScreenTip:=" - Click here to follow the hyperlink", _
TextToDisplay:="Click Here"
End Sub

Quick update for those who run into this problem - and for the support staff who suggest that the issue is perhaps too old to talk about:
Excel for Microsoft 365 MSO (Version 2203 Build 16.0.15028.20102) still has this bug.
It's a bit inexcusable, when typical URLs that you want to parameterize (a common usage in Excel) easily exceed 255, and most internet software has a default limit of 1024 characters... many even allow exceeding that by configuration.
This is a 12-year-old problem that has never been fixed.

Instead of writing
=CONCATENATE("Toto";"Tata")
Put Toto in cell Z1 (for exemple) and Tata in cell Z2 and write
=CONCATENATE(Z1;Z2)

Guys I think a URL Shortening VBA will help you. Here is one which I found today. It works like a charm:
http://www.jpsoftwaretech.com/shorten-urls-with-bit-ly-web-api-and-vba/

The Hyperlink function has a hard limit that can't be overstaped. I had a similar problem and I simply imported the Excel sheet into Open Office Calc and voila - everything worked instantly and the hyperlink that was to long previously can be now as long as I wanted it to be.

You can use the VBA Shell() routine to execute a browser and pass the URL to it on the command line passed via the Shell() call. Thus the URL can be any length supported by the shell mechanism.
Furthermore you can get this URL from any cell value by having the user double-click that cell. This value can be constructed from many cells via a single CONCATENATE() function call! That's right: just a single call. The CONCATENATE() will take a large number of parameters and will create a string well-bigger than 255 characters. You don't need to laboriously join many separate concatenations or use loads of "builder" cells. One will do!
The macro needs to be created by opening the VIEW CODE option when you right-click the tab at the bottom of the worksheet. Then write the following phenomenally short, simple and painless bit of code:
Option Explicit
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Selection.Count = 1 Then
If Left(Target.Value, 7) = "HTTP://" Then
Cancel = True
Shell ("""" + Range("Browser").Value + """" + " " + """" + Target.Value + """")
End If
End If
End Sub
Note that "Browser" is a named cell that should contain the unquoted path of your browser, be that IE, Opera, Mozilla or Chrome. You have to name the cell yourself, or change the macro to have a hard cell reference like "A2". And of course, that cell value must be a valid browser path!
Once you have all of this in place, you can double-click ANY cell that has a value starting with the text "HTTP://" and Excel will open the browser with that full value, no-matter how long it is. All you then need is to build your string in that cell and perhaps format it colour/font-wise to make it obvious that it is a hyperlink cell to be double-clicked. A textual hint nearby may also be in order!
Incidentally, an alternative to the Shell() line in the macro is:
ThisWorkbook.FollowHyperlink Address:=Target.Value
Whilst this will also process URLs bigger than 255 characters, I found that this FollowHyperlink() function causes the URL to be sent TWICE. Once by the Excel function itself (presumably to test it) and then again by the default browser that Excel opens! This may not be desirable (and wasn't in my case). This is why I ended up using the Shell() function instead.

You can create a hyperlink in Microsoft Word, and then copy it over to Excel.
For some reason, those hyperlink elements are not limited by the 255 character limit, but you won't be able to use the HYPERLINK() function.
Source

Assuming you do not have very many hyperlink URLs >255 characters, just use the Link function. The link function is available from the right-click menu. No need to go to Word or any other MSOffice application.
I know this works as I have a URL that is 281 characters long and that one works.
I only have two very long URLs in my sheet so when/if they need updating I am making a note that they must be done in the target cell vs. on my sheet of hyperlink addresses.

Working off of Andreas J's answer, you can use the below VBA code snippet to generate a column of hyperlinks from a column of plain-text URIs. Assuming column A contains the plain-text URIs and column B contains the desired link text, the following code loops through each row in Range("A:C") and generates a hyperlink in column C:
Sub createLink(a As Range, b As Range, c As Range)
Dim curCell As Range
Dim longHyperlink As String
Dim linkText As String
Set curCell = a
longHyperlink = b
linkText = c
curCell.Hyperlinks.Add Anchor:=curCell, _
Address:=longHyperlink, _
SubAddress:="", _
ScreenTip:="", _
TextToDisplay:=linkText
End Sub
Sub insertLinks()
Dim a As Range, b As Range
Set a = Range("A:C")
For Each b In a.Rows
Dim curCell As Range, longHyperlink As Range, linkText As Range
Set curCell = b.Cells().Item(1, 3)
Set longHyperlink = b.Cells().Item(1, 1)
Set linkText = b.Cells().Item(1, 2)
If longHyperlink = "" Then
Exit For
End If
createLink curCell, longHyperlink, linkText
Next
End Sub

Related

Printing out ActiveCell value on VBA

I'm trying to make a button which on click will print out the value of a cell as a string and not the appearance of the cell itself (if that makes sense) using the .PrintOut method in VBA. That cell is the active cell, whose value I set based on the cell next to it. Here is my code:
Sub Graphic2_Click()
Dim MyNumber as Integer
MyNumber = ActiveCell.Offset(-1, 0) + 1
ActiveCell.Value = MyNumber
ActiveCell.Printout
End Sub
I also tried MyNumber.PrintOut but I get an "Invalid Qualifier" error.
Am I missing out something too simple?
Please, try the next code. It use a temporary 'helper cell' where the format to be pasted (and recuperated after printing out):
Sub Graphic2_Click()
Dim helperCell As Range
With ActiveCell
.value = CLng(Offset(-1, 0)) + 1
Set helperCell = .Offset(1) 'it may be any cell to temporarilly be used
.Copy
helperCell.PasteSpecial xlPasteFormats
.ClearFormats
.PrintOut
helperCell.Copy
.PasteSpecial xlPasteFormats: helperCell.ClearFormats
End With
End Sub
To literally print just the contents of the cell:
Clear number formatting for the specified cell
Autofit column width for that column
Turn off gridlines
Turn off row and column headings
Set print area to the single cell, dismissing any warnings
Print out the active sheet
Each of these are straightforward to do in VBA, and probably straightforward to research on SO anyway.
You may also consider a mechanism to return the changed settings to their initial states afterwards. This would involve pushing (storing) the initial state to a variable or variables first, and popping (restoring) it back afterwards.
Explanation:
The VBA method .PrintOut is something you do to a worksheet, not a cell or its contents. Therefore, to get what you need, you need to set up the worksheet for printing so that the only thing that will appear is the contents of your chosen cell. This is what the above steps do.
For more information about the .PrintOut method, see:
https://learn.microsoft.com/en-us/office/vba/api/excel.sheets.printout
Or, to continue what the OP tried:
You could try something like:
ActiveCell.Formula = Range(ActiveCell.Offset(-1,0)).Value2 + 1
If this does not work, try:
ActiveCell.Formula = Range(ActiveCell.Offset(-1,0).Address).Value2 + 1
Or try these without the + 1 on the end, to verify that the rest of the formula is working the way you want it too. As mentioned, you may get a type mismatch issue causing an error if you don't trap first for whether the referenced cell contains a number.
.Formula in this example is how I am setting the content of the cell, and it can be used even when setting a value not necessarily literally a formula. You could use Value instead if you prefer.
.Value2 is a robust method of extracting the evaluated content of the source cell, as a value instead of as a formula.
The PrintOut method is to print a worksheet, not a range or single cell.
Note: This answer is not tested, as I am not near Excel right now.
Also... it's possible that there could be much simpler ways to do what you are trying to accomplish. Could you provide a bit more detail about the context of what you are trying to do.

Convert vlookup to more than 255 characters via Excel VBA

I am looking for reverse vlookup with more than 255 characters in Excel VBA.
This is the formula based one which I took from this website.
=INDEX(F2:F10,MATCH(TRUE,INDEX(D2:D10=A2,0),0))
I have try to convert it in VBA. Here below sample code
Sub test()
'concat
Range("i1") = WorksheetFunction.TextJoin(" ", True, Range("g1:h1"))
'lookup
Sal1 = Application.WorksheetFunction.Index(Sheets("sheet1").Range("a1:a2"), Application.WorksheetFunction.Match(True, Application.WorksheetFunction.Index(Sheets("sheet1").Range("i1:i1") = Range("i1").Value, 0), 0))
'=INDEX($W$3:$W$162,MATCH(TRUE,INDEX($W$3:$W$162=U3,0),0))
End Sub
It works well but it didn't when i change the range("i1:i1") to range("i1:i2")
I'm not sure what that worksheet formula does that =INDEX(F2:F11,MATCH(A2,D2:D11,FALSE)) doesn't do.
This part Index(Sheets("sheet1").Range("i1:i2") = Range("i1").Value, 0) is comparing a 2-d array to a single value, which should result in a Type Mismatch error. Whenever you reference a multi-cell range's Value property (Value is the default property in this context), you get a 2-d array even if the range is a single column or row.
You could fix that problem with Application.WorksheetFunction.Transpose(Range("D1:D10")) to turn it into a 1-d array, but I still don't think you can compare a 1-d array to a single value and have it return something that's suitable for passing into INDEX.
You could use VBA to create the array's of Trues and Falses, but if you're going to go to that trouble, you should just use VBA to do the whole thing and ditch the WorksheetFunction approach.
I couldn't get it to work when comparing a single cell to a single cell like you said it did.
Here's one way to reproduce the formula
Public Sub test()
Dim rFound As Range
'find A2 in D
Set rFound = Sheet1.Range("D1:D10").Find(Sheet1.Range("A2").Value, , xlValues, xlWhole)
If Not rFound Is Nothing Then
MsgBox rFound.Offset(0, 2).Value 'read column f - same position as d
End If
End Sub
If that simpler formula works and you want to use WorksheetFunction, it would look like this
Public Sub test2()
Dim wf As WorksheetFunction
Set wf = Application.WorksheetFunction
MsgBox wf.Index(Sheet1.Range("F2:F11"), wf.Match(Sheet1.Range("A2").Value, Sheet1.Range("D2:D11"), False))
End Sub
Function betterSearch(searchCell, A As Range, B As Range)
For Each cell In A
If cell.Value = searchCell Then
betterSearch = B.Cells(cell.Row, 1)
Exit For
End If
betterSearch = "Not found"
Next
End Function
i found this code from above link and it is useful for my current search.Below examples i try to get value..
Kindly consider Row 1 to 5 as empty for A and B column because my table always start from Row 6
Row
A Column
B Column
6
54
a
7
55
b
8
56
c
VBA Code:
Sub look_up ()
Ref = "b"
look_up = betterSearch(Ref, Range("B6:B8"), Range("A6:A8"))
End Sub
it show Empty while use Range("B6:B8"), Range("A6:A8")
but when changing the range from B6 and A6 to B1 and A1 (Range("B1:B8"), Range("A1:A8") )it gives the value...
My question is "can get the values from desired range"
Expressing matches via VBA
I like to know if there (are) any possibilities to convert this formula.
=INDEX(F2:F10,MATCH(TRUE,INDEX(D2:D10=A2,0),0))
So "reverse VLookUp" in title simply meant to express the (single) formula result via VBA (btw I sticked to the cell references in OP, as you mention different range addresses in comments).
This can be done by simple evaluation to give you a starting idea:
'0) define formula string
Dim BaseFormula As String
BaseFormula = "=INDEX($F$2:$F$10,MATCH(TRUE,INDEX($D$2:$D$10=$A2,0),0))"
'1) display single result in VB Editor's immediate
Dim result
result = Evaluate(BaseFormula)
Debug.Print IIf(IsError(result), "Not found!", result)
On the other hand it seems that you have the intention to extend the search string range
from A2 to more inputs (e.g. till cell A4). The base formula wouldn't return a results array with this formula,
but you could procede as follows by copying the start formula over e.g. 3 rows (note the relative address ...=$A2 to allow a row incremention in the next rows):
'0) define formula string
Dim BaseFormula As String
BaseFormula = "=INDEX($F$2:$F$10,MATCH(TRUE,INDEX($D$2:$D$10=$A1,0),0))"
'2) write result(s) to any (starting) target cell
'a)Enter formulae extending search cells over e.g. 3 rows (i.e. from $A2 to $A4)
Sheet3.Range("H2").Resize(3).Formula2 = BaseFormula
'b) optional overwriting all formulae, if you prefer values instead
'Sheet3.Range("H2").Resize(3).Value = Tabelle3.Range("G14").Resize(3).Value
Of course you can modify the formula string by any dynamic replacements (e.g. via property .Address(True,True,External:=True) applied to some predefined ranges to obtain absolute fully qualified references in this example).
Some explanations to the used formulae
The formula in the cited link
=INDEX(F2:F10,MATCH(TRUE,INDEX(D2:D10=A2,0),0))
describes a way to avoid an inevitable #NA error when matching strings with more than 255 characters directly.
Basically it is "looking up A2 in D2:D10 and returning a result from F2:F10" similar to the (failing) direct approach in such cases:
=INDEX(F2:F11,MATCH(A2,D2:D11,FALSE))
The trick is to offer a set of True|False elements (INDEX(D2:D10=A2,0))
which can be matched eventually without problems for an occurence of True.
Full power by Excel/MS 365
If, however you dispose of Excel/MS 365 you might even use the following much simpler function instead
and profit from the dynamic display of results in a so called spill range.
That means that matches can be based not only on one search string, but on several ones (e.g. A1:A2),
what seems to solve your additional issue (c.f. last sentence in OP) to extend the the search range as well.
=XLOOKUP(A1:A2,D2:D10,F2:F10,"Not found")

Switch Worksheet Names without Updating References to those Sheets

My file has two identical Worksheets for users to input two different sets of assumption variables, called "InputA" and "InputB". I want to quickly switch which Input sheet is feeding into the other sheets of the model.
Using Find and Replace took over 5 minutes, and there were over 350,000 references to "InputA".
I tried the following macro, which takes an instant to run, but unfortunately also changes all references in the workbook, effectively keeping everything referenced to the original input sheet.
Sheets("InputA").Name = "temp"
Sheets("InputB").Name = "InputA"
Sheets("temp").Name = "InputB"
Is there a way to execute the macro but prevent any references to worksheets from changing to the new sheet name, basically freezing everything except the sheet name change? Or perhaps any other solution that will work quickly? I don't want to go through 350,000 instances and rewrite using INDIRECT(), as that is the only other solution I've seen, because my references are complex and nested and that will take an age.
Thanks.
Assuming that your 2 Input-Sheets have the same structure, I would suggest the following:
Create a named range on Workbook-level, name it for example InputData. This range should contain all data from InputA.
Create a helper-sheet and name it Input - you can later set it to hidden.
Mark the range in the new sheet that is exactly the size of the Input-Data-Range and enter the formula =InputData as Array-formula. You can do so by entering Ctrl+Shift+Enter. The formula should have curly brackets and the sheet should now display the data of InputA.
Change all you formulas to refer to the helper Sheet Input instead of InputA.
Create a macro:
Sub switchInput()
Const sheetAName = "InputA"
Const sheetBName = "InputB"
With ThisWorkbook.Names("inputData")
If InStr(.RefersTo, sheetAName) > 0 Then
.RefersTo = Replace(.RefersTo, sheetAName, sheetBName)
Else
.RefersTo = Replace(.RefersTo, sheetBName, sheetAName)
End If
End With
End Sub
This routine will just change the definition of the named range to point either to the first or second input sheet. As a consequence, the helper sheet will show the data of the selected Input-Sheet. All your formulas itself stays unchanged.
As stated in the comments, you could take the approach recommended by Damian and use a conditional in all relevant cells. The generic conditional would be
=IF(A1="InputA",FORMULA INPUTA,FORMULA INPUTB)
This formula makes A1 the cell that decides which input to pull. This will make changing the around 350.000 output formulas in your workbook the bottleneck, the following macro takes care of changing all the formulas to conatin the conditional:
Sub changeFormulas()
Dim rng As Range, cll As Range
Set rng = shOutput.Range("A2:C10") 'Your relevant worksheet and range here
Dim aStr As String, bStr As String, formulaStr As String
aStr = "InputA"
bStr = "InputB"
For Each cll In rng
If cll.HasFormula And InStr(1, cll.Formula, aStr, 1) Then
formulaStr = Right(cll.Formula, Len(cll.Formula) - 1)
cll.Formula = "=IF(A1=" & Chr(34) & aStr & Chr(34) & "," & formulaStr & "," & Replace(formulaStr, aStr, bStr) & ")" 'Change A1 to the reference most suited for your case
End If
Next cll
End Sub
This might take a bit of time, since it has to access all the relevant cells one by one, but it will only have to run once.
To explain: This macro will go through all the cells in your range rng specified at the top. If a cell has a formula in it and the formula contains "InputA" it will change that formula to fit the generic conditional (with the cells own formula of course). Chr(34) is the quotation mark ", I find using Chr(34) more readable than multiple quotation marks """, but that is just preference.

How can I convert between 2 currencies USD and AED #rate of 3.68 throughout the rest of my workbook but only in selected cell ranges on each sheet?

For example. I want my intro sheet "Main Sheet" to have an option to switch the workbook between currencies. USD and AED at the rate of 3.68. Some cells are referencing other cells in different sheets, so I don't want to change the cell references, I only need to calculate the rate in specific cells within each sheet.
How can I accomplish this preferably using a check box or button for easy converting from the start. I'm using excel for Mac. Thank you
Create a cell with a validation drop-down allowing to choose between AED and USD. Convert that cell to a named range for easy referencing throughout the workbook. You might call it "Curr", short for "Currency" (short because it will be used often).
I recommend that you create a similar cell somewhere where you enter the rate, currently 3.68 but plan on changing the rate in that cell only and have it applied to all the workbook. Name that cell as "Rate".
Now all cells containing values which you may want switched would be subject to the following formula. =[CellValue] * IF(Curr = "AED", Rate, 1). This formula presumes that the values are all entered in USD. If they are entered in AED the formula should look as follows. = ROUND([CellValue] / IF(Curr = "AED", 1, Rate), 2)
As you see, this solution would require the original cell values to be recorded somewhere, meaning, the cells used for data capture can't be the same as the ones used for data display. If you wish to insist on capture and display being in the same cell you would need code to do the conversion.
On the face of it this seems simple: When the Curr selection is changed, all cells with affected values are re-calculated. In practise this would end in disaster because there are 1001 ways in which something might go wrong and then you would lose all your data, not knowing whether the values are USD or AED at that moment.
Therefore the starting point needs to be to separate data capture and data display. Once that is done workheet functions might well be not only the easiest but also the most efficient way of achieving what you want.
I'm going to assume that you want to have the conversion on the input cell and not all of your cells are formulas and that a lot of the cells you want to convert are values. You should seriously consider the answer to split out input vs display, it will be much more foolproof and protected from any logic that may break your workbook.
If you're keen on this pathe then do the following, but, before you do ... BACKUP YOUR WORKBOOK. Any tests I've done with the below code are not breaking but I don't have your workbook, therefore, I make no guarantees.
Firstly, you need a cell that gives you the current exchange rate. You need to give that cell a named range of ExchangeRate.
In my workbook, that cell contains a formula ...
=IF(B1="USD",1,3.68)
It looks like this ...
... and cell B1 has a validation attached to it that allows you to select from 2 currencies, AED or USD.
You said you want to be able to ensure that only a selection of cells will be converted. To make sure we ring fence just those cells, you need to create a named range ON EACH SHEET that includes all of those cells.
The name of that range needs to be called CellsToConvert and you can do that through the Name Manager. When creating the named range, make sure you specify the worksheet you're creating it for, do not selected the "Workbook" option.
... the below shows the sporadic range I used on the first sheet. All coloured cells a part of that range. The green cells contain values and the yellow cells contain formulas.
At the end of the day, that range can be huge and across different sheets but it should work.
Now, add the following code into the ThisWorkbook object within the VBA editor ...
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Dim objCell As Range, dblExRate As Double, strFormula As String, objSheet As Worksheet
Dim strNewFormula As String, strOpeningChar As String, bIsFormula As Boolean
Dim objCells As Range, strError As String, strExRateRangeName As String
strExRateRangeName = "ExchangeRate"
dblExRate = Range(strExRateRangeName)
Application.EnableEvents = False
For Each objSheet In Worksheets
On Error Resume Next
strError = ""
Err.Clear
Set objCells = objSheet.Range("CellsToConvert")
strError = Err.Description
On Error GoTo 0
If strError = "" Then
For Each objCell In objCells
strFormula = objCell.FormulaR1C1
bIsFormula = False
' Check to make sure this field contains a formula.
If Left(strFormula, 1) = "=" And objCell.NumberFormat <> "#" Then
bIsFormula = True
End If
If dblExRate = 1 Then
' Base currency selected.
' Check to see if the cell contains a formula, if it does,
' convert it back to a value
If bIsFormula Then
' It's a formula and the cell is not set to text, proces it back
' to its original value, that could still be a formula.
' Remove all of the exchange rate components we would've added as
' a part of this routine.
strNewFormula = Replace(strFormula, ") * " & strExRateRangeName, "")
' Check to see if the formula has changed against the previous statement,
' if it has, then it contained the custom additions, otherwise, it didn't.
If strFormula <> strNewFormula Then
strNewFormula = Mid(strNewFormula, 3)
' Check to see if the new value is numeric, if it is, remove the leading
' equals sign as it wasn't originally a formula, or, at least it doesn't
' need to be a formula.
If IsNumeric(strNewFormula) Then
objCell.Value = strNewFormula
Else
objCell.FormulaR1C1 = "=" & strNewFormula
End If
End If
End If
Else
' Something other than the base currency has been selected.
strNewFormula = objCell.FormulaR1C1
If InStr(1, strNewFormula, strExRateRangeName, vbTextCompare) = 0 Then
If bIsFormula Then strNewFormula = Mid(objCell.FormulaR1C1, 2)
objCell.FormulaR1C1 = "=(" & strNewFormula & ") * " & strExRateRangeName
End If
End If
Next
End If
Next
Application.EnableEvents = True
End Sub
... once you've done all of the above, it should work for you. Performance could be tested if the workbook is large but that's something you'll need to check for yourself.
If you change a cell and it's within one of those ranges AND the currency of USD is not selected, you'll see the input value changed to a formula after you hit enter. That's pretty neat when you think about it but may not be for you.
One last thing to note, if your range contains broken links, the calculation for that sheet will fail and my code will not notify you of that.
This adds another option for you but is riskier than the first answer. There's nothing like options. :-)

How do I reference a cell range from one worksheet to another using excel formulas?

I have a single worksheet with sheets Sheet1 and Sheet2 and I am trying to reference a range of cells from Sheet2 to Sheet1
I know how to reference worksheet cells such as =Sheet2!A1 but how can I do the same for a cell range such as A1:F1 I tried =Sheet2!A1:F1 but it does not like the syntax.
I need to use Excel Formulas for this if possible.
Simple ---
I have created a Sheet 2 with 4 cells and Sheet 1 with a single Cell with a Formula:
=SUM(Sheet2!B3:E3)
Note, trying as you stated, it does not make sense to assign a Single Cell a value from a range. Send it to a Formula that uses a range to do something with it.
The formula that you have is fine. But, after entering it, you need to hit Control + Shift + Enter in order to apply it to the range of values. Specifically:
Select the range of values in the destination sheet.
Enter into the formula panel your desired formula, e.g. =Sheet2!A1:F1
Hit Control + Shift + Enter to apply the formula to the range.
Ok Got it, I downloaded a custom concatenation function and then just referenced its cells
Code
Function concat(useThis As Range, Optional delim As String) As String
' this function will concatenate a range of cells and return one string
' useful when you have a rather large range of cells that you need to add up
Dim retVal, dlm As String
retVal = ""
If delim = Null Then
dlm = ""
Else
dlm = delim
End If
For Each cell In useThis
if cstr(cell.value)<>"" and cstr(cell.value)<>" " then
retVal = retVal & cstr(cell.Value) & dlm
end if
Next
If dlm <> "" Then
retVal = Left(retVal, Len(retVal) - Len(dlm))
End If
concat = retVal
End Function
If you wish to concatenate multiple cells from different sheets, and you also want to add a delimiter between the content of each cell, the most straightforward way to do it is:
=CONCATENATE(Sheet1!A4, ", ", Sheet2!A5)
This works only for a limited number of referenced cells, but it is fast if you have only of few of these cells that you want to map.
You can put an equal formula, then copy it so reference the whole range (one cell goes into one cell)
=Sheet2!A1
If you need to concatenate the results, you'll need a longer formula, or a user-defined function (i.e. macro).
=Sheet2!A1&Sheet2!B1&Sheet2!C1&Sheet2!D1&Sheet2!E1&Sheet2!F1
Its quite simple but not easy to discover --- Go here to read more. its from the official microsoft website
Step 1 -
Click the cell or range of the source sheet (that contains the data you want to link to)
Step 2
Press Ctrl+C, or go to the Home tab, and in the Clipboard group, click Copy Button image .
Step 3
Clipboard group on the Home tab
Step 4
Press Ctrl+V, or go to the Home tab, in the Clipboard group, click Paste Link Button. By default, the Paste Options Button image button appears when you paste copied data.
Step 5
Click the Paste Options button, and then click Paste Link .
I rewrote the code provided by Ninja2k because I didn't like that it looped through cells. For future reference here's a version using arrays instead which works noticeably faster over lots of ranges but has the same result:
Function concat2(useThis As Range, Optional delim As String) As String
Dim tempValues
Dim tempString
Dim numValues As Long
Dim i As Long, j As Long
tempValues = useThis
numValues = UBound(tempValues) * UBound(tempValues, 2)
ReDim values(1 To numValues)
For i = UBound(tempValues) To LBound(tempValues) Step -1
For j = UBound(tempValues, 2) To LBound(tempValues, 2) Step -1
values(numValues) = tempValues(i, j)
numValues = numValues - 1
Next j
Next i
concat2 = Join(values, delim)
End Function
I can't help but think there's definitely a better way...
Here are steps to do it manually without VBA which only works with 1d arrays and makes static values instead of retaining the references:
Update cell formula to something like =Sheet2!A1:A15
Hit F9
Remove the curly braces { and }
Place CONCATENATE( at the front of the formula after the = sign and ) at the end of the formula.
Hit enter.
If these worksheets reside in the same workbook, a simple solution would be to name the range, and have the formula refer to the named range. To name a range, select it, right click, and provide it with a meaningful name with Workbook scope.
For example =Sheet1!$A$1:$F$1 could be named: theNamedRange. Then your formula on Sheet2! could refer to it in your formula like this: =SUM(theNamedRange).
Incidentally, it is not clear from your question how you meant to use the range. If you put what you had in a formula (e.g., =SUM(Sheet1!A1:F1)) it will work, you simply need to insert that range argument in a formula. Excel does not resolve the range reference without a related formula because it does not know what you want to do with it.
Of the two methods, I find the named range convention is easier to work with.

Resources