I have a named range by name 'AlgeriaBchar'. (Algeria-> countryname and Bchar-> statename)
I use constraint on city dropdown as content in country dropdown + state dropdown (i.e. E7 + F7).
But as we can see in img staename is 'Béchar' which i need to remove char 'é' as it doesnt fit in a-z, A-Z, 0-9.
I also need to remove any blank spaces, hiphns, square brackets, apostrophy marks in country and state dropdown contents
I m not getting in which sequence I should put these fucntions to get it to 'AlgeriaBchar'
For better understanding I provided indentation to data validation fucntion in excel.
I'll be putting this fucntion in city dropdown's validaity constraint.
I may need to evaluate each character in a string which will need for loop. MID( E7, 1 ,1 ) gives me only 1st chracter. How can I loop it till the length of the string.
can anyone suggest me.
=IF(
NOT(
AND( CODE( MID( E7, 1 ,1 ) ) >=65 , CODE( MID( E7, 1 ,1 ) ) <=90 )
)
AND(
NOT(
AND( CODE( MID( E7, 1 ,1 ) ) >=97 , CODE( MID( E7, 1 ,1 ) ) <=122 )
)
)
AND(
NOT(
AND( CODE( MID( E7, 1 ,1 ) ) >=48 , CODE( MID( E7, 1 ,1 ) ) <=57 )
)
)
, SUBSTITUTE( E7, MID( E7, 1 ,1 ), "" ) ,""
)
INDIRECT(
SUBSTITUTE(
SUBSTITUTE(
SUBSTITUTE(
SUBSTITUTE(
SUBSTITUTE(UPPER($E$7)," ","")
,"-","")
,"'","")
,"[","")
,"]","")
)
)
You may want to use a macro for that. Consider this one (based on this article from extendoffice.com)
1) Hold down the Alt + F11 keys in Excel, and it opens the Microsoft Visual Basic for Applications window.
2) Click Insert > Module, and paste the following macro in the Module Window.
Function StripAccent(thestring As String)
Dim A As String * 1
Dim B As String * 1
Dim i As Integer
Const AccChars = "ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðñòóôõöùúûüýÿ-[]' "
For i = 1 To Len(AccChars)
A = Mid(AccChars, i, 1)
thestring = Replace(thestring, A, "")
Next
StripAccent = thestring
End Function
Function TrimmedConcat(A As String, B As String)
TrimmedConcat = StripAccent(A) & StripAccent(B)
End Function
Then in your document, click in a cell, and use TrimmedConcat as if it was a normal function, selecting the country name as the first argument and the city name as the second.
In your example =TrimmedConcat(E7,F7)
I hope that helps!
Related
I would normally have coded my output prior if I had direct access to the system. Unfortunately, my current customer how shall I say, slightly antiquated. I have been given a csvde dump from active directory. Within Excel how I can extract all the 'CN=*,' values in cell A1 and list them into the adjacent cell A2?
A1
A2
CN=Organization Management,OU=Microsoft Exchange Security Groups,DC=test,DC=local;CN=Discovery Management,OU=Microsoft Exchange Security Groups,DC=test,DC=local;CN=VPN Users,OU=Groups,OU=TEST,DC=test,DC=local;CN=Debugger Users,CN=Users,DC=test,DC=local;CN=Wireless Users,OU=Groups,OU=TEST,DC=test,DC=local;CN=Users,DC=test,DC=local;CN=Exchange Public Folder Administrators,OU=Microsoft Exchange Security Groups,DC=test,DC=local;CN=Exchange Organization Administrators,OU=Microsoft Exchange Security Groups,DC=test,DC=local
With Excel 365 for Mac, you can do:
=LET( txt, A1,
s, SEQUENCE(LEN(txt)),
hdrSeq, (MID(txt,s,3)="CN=")*s, tlrSeq, (MID(txt,s,1)=",")*s,
header, FILTER( hdrSeq, hdrSeq > 0 ), trailer, FILTER( tlrSeq, tlrSeq > 0 ),
nxtTrlr, INDEX(trailer, IFERROR( XMATCH(header,trailer,1,-1), 1 ) ),
MID( txt, header, nxtTrlr-header) )
where A1 contains the target text that you want to parse.
If you need it to spill right, this will do it:
=LET( txt, A1,
s, SEQUENCE(LEN(txt)),
hdrSeq, (MID(txt,s,3)="CN=")*s, tlrSeq, (MID(txt,s,1)=",")*s,
header, FILTER( hdrSeq, hdrSeq > 0 ), trailer, FILTER( tlrSeq, tlrSeq > 0 ),
nxtTrlr, INDEX(trailer, IFERROR( XMATCH(header,trailer,1,-1), 1 ) ),
TRANSPOSE( MID( txt, header, nxtTrlr-header) ) )
Adding TEXTJOIN
Note JvdV's answer within the comments - super sleek and non-intuitive.
If you need this as a single cell text, then:
=LET( txt, A1,
s, SEQUENCE(LEN(txt)),
hdrSeq, (MID(txt,s,3)="CN=")*s, tlrSeq, (MID(txt,s,1)=",")*s,
header, FILTER( hdrSeq, hdrSeq > 0 ), trailer, FILTER( tlrSeq, tlrSeq > 0 ),
nxtTrlr, INDEX(trailer, IFERROR( XMATCH(header,trailer,1,-1), 1 ) ),
TEXTJOIN(",", 1, MID( txt, header, nxtTrlr-header) ) )
You may find a two-step solution useful:
use TextToColumns comand in Data tab to split string by semicolon, comma and equal signs:
use formula:
=TEXTJOIN(CHAR(10),1,"CN="&FILTER(B1:ZZ1,A1:ZY1="cn"))
I have one list starting from B1 (=UNIQUE(A1:A8)), and another list starting from D1 (=UNIQUE(C1:C8)). Thus =B1# and =D1# in other cells both spill.
Now, I would like to know if we could find one formula to combine List B1# and List D1# (extract only unique values) by dynamic array functions, LAMBDA, LET, etc.
I don't want to move the position of the two lists. Does anyone have any good idea?
I may not be following what you want the shape to be, but here are two shapes:
Side-by-Side
=CHOOSE({1,2},B1#,D1#)
If you want it to take the original A and C columns as input and do all the work, then:
=CHOOSE({1,2},UNIQUE(FILTER(A:A,NOT(ISBLANK(A:A)))),UNIQUE(FILTER(C:C,NOT(ISBLANK(C:C)))))
or a LET version of the same which does not require retyping the inputs:
=LET( Ltrs, A:A,
Nmbrs, C:C,
CHOOSE( {1,2},
UNIQUE(FILTER(Ltrs,NOT(ISBLANK(Ltrs)))),
UNIQUE(FILTER(Nmbrs,NOT(ISBLANK(Nmbrs)))) ) )
End-on-End
=LET( uLtrs, B1#,
uNmbrs, D1#,
ltrCt, ROWS(uLtrs),
idx, SEQUENCE( ltrCt + ROWS(uNmbrs) ),
IF( idx <= ltrCt, uLtrs, INDEX( uNmbrs, idx-ltrCt ) ) )
Similar as above, if you want it to take the original A and C columns as input and do all the work, then:
=LET( Ltrs, A:A,
Nmbrs, C:C,
uLtrs, UNIQUE(FILTER(Ltrs,NOT(ISBLANK(Ltrs)))),
uNmbrs, UNIQUE(FILTER(Nmbrs,NOT(ISBLANK(Nmbrs)))),
ltrCt, ROWS(uLtrs),
idx, SEQUENCE( ltrCt + ROWS(uNmbrs) ),
IF( idx <= ltrCt, uLtrs, INDEX( uNmbrs, idx-ltrCt ) ) )
Both spill the results.
Place the following code into cell F2 and drag formula downwards to F14. This will give you a unique list of both Column A and Column D
=IF(IFERROR(IF(INDEX($A$1:$A$99999,MATCH(0,COUNTIF($F$1:F1,$A$1:$A$99999),0))=0,NA(),INDEX($A$1:$A$99999,MATCH(0,COUNTIF($F$1:F1,$A$1:$A$99999),0))),INDEX($C$1:$C$99999,MATCH(0,COUNTIF($F$1:F1,$C$1:$C$99999),0)))=0,NA(),IFERROR(IF(INDEX($A$1:$A$99999,MATCH(0,COUNTIF($F$1:F1,$A$1:$A$99999),0))=0,NA(),INDEX($A$1:$A$99999,MATCH(0,COUNTIF($F$1:F1,$A$1:$A$99999),0))),INDEX($C$1:$C$99999,MATCH(0,COUNTIF($F$1:F1,$C$1:$C$99999),0))))
Let me know if you need it to behave differently.
I've got following data as result from a query. As example 2 rows but in total around 30000 rows.
Some timestamps are empty because no row in that table.
agr_no
timestamp1
timestamp2
timestamp3
00000080064
2005-08-17-09.29.01.427337
2005-08-17-09.29.01.351888
00000080065
2002-04-29-15.04.58.714606
2013-11-18-13.11.46.494690
I would like to have in the next column an indication about which timestamp is the greatest.
For example:
agr_no
timestamp1
timestamp2
timestamp3
Result
00000080064
2005-08-17-09.29.01.427337
2005-08-17-09.29.01.351888
TS1
00000080065
2002-04-29-15.04.58.714606
2013-11-18-13.11.46.494690
TS3
Tried many things but always in trouble with the format of the timestamp so no comparison is possible.
Thanks a lot.
This is quite ugly but,
You can convert your values to dates and then just take the max date, or in this instance, the index of the matched date.
="TS" & MATCH(MAX(IFERROR(DATEVALUE(LEFT(A2:C2,10))+TIME(MID(A2:C2,12,2),MID(A2:C2,15,2),MID(A2:C2,18,2)+(RIGHT(A2:C2,6)/1000)),0)),IFERROR(DATEVALUE(LEFT(A2:C2,10))+TIME(MID(A2:C2,12,2),MID(A2:C2,15,2),MID(A2:C2,18,2)+(RIGHT(A2:C2,6)/1000)),0),0)
Note this assumes the formats of the string dates are either blank OR in strictly in the below format which is consistent with the limited inputs you gave us
yyyy-mm-dd.hh.mm.ss.######
FYI - Your milliseconds value is strange. On your first row the milliseconds actually equates to minutes
Assuming your data is located at [A1:D27] and based on this formula to convert the string TimeStamp to a double:
= IFERROR( VALUE( SUBSTITUTE( SUBSTITUTE( SUBSTITUTE( B2,
"-", " ", 3 ), ".", ":" ), ":", ".", 3 ) ), 0 )
Enter this FormulaArray in E2, then copy E2 downwards till last row:
= "TS" & MATCH( MAX(
IFERROR( VALUE( SUBSTITUTE( SUBSTITUTE( SUBSTITUTE( B2:D2,
"-", " ", 3 ), ".", ":" ), ":", ".", 3 ) ), 0 ) ),
IFERROR( VALUE( SUBSTITUTE( SUBSTITUTE( SUBSTITUTE( B2:D2,
"-", " ", 3 ), ".", ":" ), ":", ".", 3 ) ), 0 ), 0 )
FormulaArray are entered holding down ctrl+shift+enter simultaneously, the formula would be wrapped within { and } if entered correctly.
Ideally we would like to avoid using VBA for this (if it's possible).
I have provided two sample spreadsheets to illustrate the issue as it's probably better with an example rather than giving confusing explanations.
Main sheet: https://www.dropbox.com/s/xjb5of65ru204y4/Main.xlsx?dl=0
Suppliers sheet: https://www.dropbox.com/s/hcjzwatk2m67a94/Suppliers.xlsx?dl=0
Basically, we need to pull a range of an unknown length starting from an unknown offset from a closed workbook, then use MATCH to find the row index of a value we're looking for and return the value.
We tried three different methods. All formulas works when the workbook is open but we need a solution to use without the workbook open.
I didn't look into using INDIRECT since MS strictly states that INDIRECT is not compatible with closed workbook.
Here are the formulas with indentation for better visual:
Method #1: Using index + count(if()) (array)
This solution returns #REF! when the external workbook is closed
INDEX(
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$G:$G,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
)
:
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$G:$G,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
+
COUNT(
IF('Z:\...\[Suppliers.xlsx]suppliers'!$A:$A=$L$9,1)
)-1
)
,
MATCH(
K11,
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$D:$D,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
)
:
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$D:$D,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
+
COUNT(
IF('Z:\...\[Suppliers.xlsx]suppliers'!$A:$A=$L$9,1)
)-1
)
,0)
,0)
Method #2: Using index + countif()
This solution returns #VALUE! when the external workbook is closed
INDEX(
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$G:$G,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
)
:
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$G:$G,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
+
COUNTIF('Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,$L$9))-1
)
,
MATCH(
K11,
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$D:$D,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
)
:
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$D:$D,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
+
COUNTIF('Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,$L$9))-1
)
,0)
,0)
Method #3: Using index + sumproduct()
This solution returns #REF! when the external workbook is closed
INDEX(
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$G:$G,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
)
:
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$G:$G,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
+
SUMPRODUCT( -- ('Z:\...\[Suppliers.xlsx]suppliers'!$A:$A=$L$9))-1
)
,
MATCH(
K11,
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$D:$D,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
)
:
INDEX('Z:\...\[Suppliers.xlsx]suppliers'!$D:$D,
MATCH($L$9,'Z:\...\[Suppliers.xlsx]suppliers'!$A:$A,0)
+
SUMPRODUCT( -- ('Z:\...\[Suppliers.xlsx]suppliers'!$A:$A=$L$9))-1
)
,0)
,0)
If I understand correctly, the tricky bit is building a dynamic range using INDEX(ref,row,col):INDEX(ref,row,col) since every bits works on their own but when used in this fashion it returns an error.
Note: You might need to update the absolute path to the spreadsheet suppliers.xlsx in main.xlsx if you download the provided demo
All help is gladly appreciated!
I have gone through the variations on these and each has a different solution depending on how the names are in a cell. Let me make it clear. I have an excel sheet containing the names of my colleagues from my college days. The names are in no particular format. The "Name" column has the names like:
1) Dipak C. Chopra
2) Amar D Pathak
3) Lara Naik
4) Reshma Laxman Bhavsar
So as can be seen, some have simply a middle initial, some have it with a period and some have it missing while some have a full middle name. What I wish to do is to rewrite these names in another column by last name so that it turns out like:
1) Chopra Dipak C.
2) Pathak Amar D
3) Naik Lara
4) Bhavsar Reshma Laxman
I can do it but I have to use formulae with variations depending the name in the cell: e.g.
=TRIM(RIGHT(B2,LEN(B2)-FIND(" ",B2)) & " " & LEFT(B2,FIND(" ",B2))) for the 3rd entry
=TRIM(RIGHT(B4,LEN(B4)-FIND(" ",B4)-1) & " " & LEFT(B4,FIND(" ",B4)+1)) for the 2nd entry
=TRIM(RIGHT(B13,LEN(B13)-FIND(" ",B13,FIND(" ",B13)+1))&" "&LEFT(B13,FIND(" ",B13,FIND(" ",B13)+1))) for the 4th entry.
My question is how can I revise this formula to give me the desired result in all the cases mentioned above?
=IF(ISERROR(FIND(" ",B2)),B2,RIGHT(B2,LEN(B2)-FIND("~",SUBSTITUTE(B2," ","~",LEN(B2)-LEN(SUBSTITUTE(B2," ","")))))&" "&LEFT(B2,FIND("~",SUBSTITUTE(B2," ","~",LEN(B2)-LEN(SUBSTITUTE(B2," ",""))))-1))
It involves doing a reverse string search to find the last space and then uses its position to cut the last name off and then add on the rest of the string to the end, if there is no spaces in the string it will just return the value is B2
Beautified
=IF(
ISERROR(
FIND(
" ",
B2
)
),
B2,
RIGHT(
B2,
LEN(
B2
) -
FIND(
"~",
SUBSTITUTE(
B2,
" ",
"~",
LEN(
B2
) -
LEN(
SUBSTITUTE(
B2,
" ",
""
)
)
)
)
) & " " &
LEFT(
B2,
FIND(
"~",
SUBSTITUTE(
B2,
" ",
"~",
LEN(
B2
) -
LEN(
SUBSTITUTE(
B2,
" ",
""
)
)
)
) - 1
)
)