How to pull specific data from different length string? - excel

I got this type of sport activity data in excel:
I try to pull just a "calorie" value from column D to another cell.
Any suggestions how to pull this data?
Tried to do it by =MID function, but those strings are different length.
Any suggestions how to pull this data?

You could try a formula like as below,
• Formula used in cell E1
=TEXTAFTER(TEXTBEFORE(D1,",""count"),"calorie"":")+0
Alternative approach, If you are not using MS365, then use the formula as shown below
• Formula used in cell F1
=REPLACE(LEFT(D1,FIND("""count",D1)-2),1,FIND("calorie",D1)+8,"")+0
Or, In MS365 using CHOOSECOLS() & TEXTSPLIT()
• Formula used in cell G1
=CHOOSECOLS(TEXTSPLIT(D1,{":",","},,1),8)/1

=TEXTBEFORE(TEXTAFTER(A1,"""calorie"":"),",")

Using VBA, you can use the Split method, since the pattern is the same:
Sub ExtractCalorie()
Dim cel As String: cel = ActiveCell.Value
'in the active cell is the string: {"duration":67,"altitude":0.0,"distance":21499,"calorie":89000,"count":0,"floor":0,"steps":0}
Debug.Print Split(cel, ",")(3) 'it returns "calorie":89000
'If only the value needed:
Debug.Print Split(Split(cel, ",")(3), ":")(1) 'it returns 89000
End Sub
It can be easily transformed in a function, which works also as UDF, to be called from a formula in cell...

Related

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")

eXcel formula for all column value in one cell separating by ","

Look at the column A contain value like the below image . I want a formula to do that .
I don't want to solution like
=CONCATENATE(A1,",",A2,",",A3,",",A4,",",A5)
Excel 2016 has a new function called TextJoin() with the syntax
=TextJoin(delimiter, ignore empty cells, range)
With this, you can use the formula
=TEXTJOIN(",",TRUE,A1:A5)
Edit after comment: It's a new formula in Excel 2016. It does not exist in 2010.
But there are many User Defined Functions (UDF) macros that do a better job than Concatenate, and that can be used in Excel 2010. For example in this post by Jon Acampora. You will need to use the VBA code in each of the spreadsheets where you want to use that special function, though, and all these spreadsheets need to be macro-enabled sheets for these special functions to work.
try this
=A1&","&A2&","&A3&","&A4
OR create custom VBA function
Public Function Join(rng As Range, delimiter As String) As String
Dim cell As Range
For Each cell In rng
Join = Join & cell.Text & delimiter
Next cell
' remove the last delimiter
Join = Left(Join, Len(Join) - Len(delimiter))
End Function
For a long list a more complex formula but one that 'auto adjusts' on copy down might suit:
=IF(A2="",LEFT(B1&A2&",",LEN(B1&A2&",")-2),B1&A2&",")
Assumes a row is inserted at the top with B1 blank. The output would be in ColumnB of the row with the first blank cell in ColumnA after Row1.

vba excel looping thru an array

I'm a rookie at vba.
I created a solution that works on a micro basis, but can't get the same code to run when I add additional parameters to that code.
I created a multiple choice quiz with answer cells which test against the answers on a separate (hidden) sheet. An adjacent cell shows Yes or No response. That functionality which I researched on the web works well. I'm trying to clear.contents for all the cells so that the user can complete the quiz, clear all responses to give it another go.
I have 395 questions which I created code to clear "Range("B2").ClearContents"
My subroutine has 395 such commands and takes 45-60 seconds. I'm looking for a more efficient solution. I don't want to clear the entire column only the 395 non-adjacent cells which have user input.
Sub Test_Clear()
Range("B2,B5,B7,B9,B11").ClearContents
End Sub
My list of cells is on Sheet2 D1:D395 Each cell in D1:D395 lists a cell on Sheet1 which I want to clear (i.e. B6, B11, B17, B22, B35 etc.) How can I reference those cells on Sheet2 and perform the ClearContents?
While you could just hard code your list in VBA instead of your Sheet2 range, here is how you could reference that list of cells in sheet2 and clear the contents all at once:
Sub clearall()
Dim rngCell, listCells As String
For Each rngCell In Sheet2.Range("D1:D395").Cells
If listCell <> "" Then listCell = listCell & "," & rngCell.Value Else listCell = rngCell.Value
Next
Sheet2.Range(listCell).ClearContents
End Sub
If you just want to clear the cells in column A which have something in them you could use this
Sheet1.Range("A:A").SpecialCells(xlCellTypeConstants).ClearContents
'or
Sheet1.Range("A1:A395").SpecialCells(xlCellTypeConstants).ClearContents
The VBA Join function can be used to join values into string, and the Excel Transpose function is needed to "flip" the column values 2D array to a 1D row values array:
stringAdress = Join([Transpose(Sheet2!D1:D395)], ",")
ThisWorkbook.Worksheets("Sheet1").Range(stringAdress).ClearContents
If any of the cells in the Sheet2!D1:D395 range are blank, the above will result in error.
In Excel 2016, the TextJoin function can be used to ignore empty cells (not tested):
stringAdress = [TextJoin(",", True, Sheet2!D1:D395)]
ThisWorkbook.Worksheets("Sheet1").Range(stringAdress).ClearContents

How to compare two different sheets and place values in their respective positions?

I would like to compare two different cells within two different spreadsheets (One sheet is a base sheet) via VBA and if they are the same, take the values beside what they're being compared to and the place values in their respective positions.
So in the picture, A is a match in both sheets so the value of 30 is copied over to the base sheet. The spreadsheets that I'm dealing with are not perfectly lined up like the image.
Please let me know if you need more clarification. Thank you!
As I've commented, you can use VLOOKUP in this case.
Assuming both your values are in Column A to B of both sheet and A1 and B1 are headers, you can try below formula in Cell B2:
=VLOOKUP(A2,Sheet2!A:B,2,0)
which will give you the result above. It is also assumed that your sheet names are Sheet1 and Sheet2.
Edit: VBA Code
Using Formula Property
With Sheets("Sheet1").Range("A2")
.Formula = "=VLOOKUP(A2,Sheet2!A:B,2,0)"
.Value = .Value
End With
Using Evaluate Method
With Sheets("Sheet1")
' 3 ways to use Evaluate method
.Range("A2").Value = [VLOOKUP(A2,Sheet2!A:B,2,0)] ' Evaluate shortcut
.Range("A2").Value = .Evaluate("VLOOKUP(A2,Sheet2!A:B,2,0)") ' explicitly
.Range("A2").Value = Evaluate("VLOOKUP(A2,Sheet2!A:B,2,0)")
End With
Using WorkSheetFunction Method - Already provided by Tom
You can use native sheet functions in VBA. Just prepend the worksheet function with 'Application.WorksheetFunction'.
Application.WorksheetFunction.VLookup(Sheets("Sheet2").Range("A2"), Sheets("Sheet2").Columns("A:B"), 2, False)
Hope that helps.

Retrieving Cell name in Excel

Is there a way of displaying the cell name of a particular cell in another cell? I would like to display the cell name in the adjacent cell so that the user is able to identify the cell name without clicking it.
ADDRESS(ROW(),COLUMN()) will give you the address, e.g. $A$1 of the current cell. Add/subtract from the row/column values (numbers) to reference the cell you are after.
If you don't want the $ then you can find and replace it with SUBSTITUTE(ADDRESS(ROW(),COLUMN()),"$","") and get just A1 for example
This function would give the name of the NamedRange the cell belongs to:
Public Function CellName(oCell As Range) As Variant
Dim oName As Name
For Each oName In ThisWorkbook.Names
If oName.RefersToRange.Parent Is oCell.Parent Then
If Not Intersect(oCell, oName.RefersToRange) Is Nothing Then
CellName = oName.Name
Exit Function
End If
End If
Next
CellName = CVErr(xlErrNA)
End Function
It loops through all the names in the workbook, and then for each name it checks if it refers to any thing in this the sheet input parameter is from. If it is then it checks if the input cell and the rages referred by the name intersect. If they do it returns the name of the range.
In Excel 2013, and maybe in some older versions too, ADDRESS() accepts third parameter that defines the format of the address to be returned with following values:
1 - Absolute (default)
2 - Absolute row/Relative column
3 - Relative row/Absolute column
4 - Relative
so lets say in cell A1
ADDRESS(ROW();COLUMN()) //outputs $A$1
ADDRESS(ROW();COLUMN();1) //outputs $A$1
ADDRESS(ROW();COLUMN();2) //outputs A$1
ADDRESS(ROW();COLUMN();3) //outputs $A1
ADDRESS(ROW();COLUMN();4) //outputs A1
If you want to display the name of cell D3 in cell A1 type:
ADDERSS(ROW(D3);COLUMN(D3);4) //outputs text D3 in cell A1
Technically, you could combine the SUBSTITUTE() and new FORMULATEXT() functions to do this, if you don't mind adding a hidden column in your sheet.
Assume cell A1 is named FOO
Add a simple reference formula in B1 to the named cell =FOO
Add a formula in C1 =SUBSTITUTE(FORMULATEXT(B2),"=","")
Hide Column B
Cell C1 will contain the value FOO (or the RC reference for unnamed cells)
Adjust as needed, your mileage (or kilometerage) may vary.
It doesn't seem to be possible, which is weird. You'd think that the cell() function should provide a way to get the name, but it doesn't. Bummer.
ActiveWorkbook.Sheets.Item(1).Cells(row, col).Name.Name
I took some 'advice' from the answer above from Adarsha. I got a similar result to the code below, with that loop and a few refinements. However my 'tip for excel' macros is to make your debugger your best friend.
Function name_of(clls)
'
name_of = ""
'
Dim nam As String
Dim rg As Range
Set rg = clls
'
nam = rg.Name.Name
'
name_of = nam
'
End Function 'name_of
A little bit of patience and perseverance, gave me exactly what I was looking for -- A user defined function to give me the defined name of a cell. What happens if the same Cell has more than one name? Try that and see. It is a simple test, so I want to leave that for you to experiment, learn and pass on your new knowledge.
This will work in very basic circumstances:
Public Function CellName(cel As Range) As Variant
Dim nm As Name
For Each nm In Names
If nm.RefersTo = "=" & cel.Parent.Name & "!" & cel.Address Then
CellName = nm.Name
Exit Function
End If
Next
CellName = CVErr(xlErrNA)
End Function
It won't work if the cell is part of a named range, it won't show multiple names for the cell, it won't work for cells included in named formulae (like =OFFSET() ranges, for example).
The
"=" & cel.Parent.Name & "!" & cel.Address
thing is pretty clunky, too. There may be a better way to do the check. Creating a Range object from the RefersTo and using Intersect() might work.
Excel does have a function "Cell()" that you can get certain properties from.
You can use =Cell("row", K9) and get back row number 9 and there's an equivalent "col" parameter but it returns the column number (11) rather than the letter.
Reference the named cell in another cell, E12 in this case, and then use this formula: ="'"&FORMULATEXT(E12). This puts an apostrophe in front so it will show the name or formula as text.
You can place your cursor in an empty cell, type = then click on the named cell. It will display the cell contents. Then you change the format of the cell to text and it will show =

Resources