Replace Values Conditionals - excel

I want to replace values based on certain conditions. I can do this for the values in a specific column but I am not sure how to convert the code to have it work for all values in a range of columns.
This is my code currently:
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
ColumnNames = Table.ColumnNames(Source),
Step1 = Table.ReplaceValue(Source,
each[L1_Grade],
else if Text.Contains([L1_Grade], "A") then "Upper"
else if Text.Contains([L1_Grade], "B") then "Middle"
else if Text.Contains([L1_Grade], "C") then "Lower"
else if Text.Contains([L1_Grade], "NaN") then ""
else if Value.Is(Value.FromText([L1_Grade]), type number) then "Num"
else [L1_Grade], Replacer.ReplaceText, ColumnNames)
in
Step1
How do I modify my code so it works for any of the columns specified using ColumnNames? I am not sure what to replace [L1_Grade] with.

Assuming, you have such table:
Then you may use following code:
let
Source = Excel.CurrentWorkbook(){[Name = "Data"]}[Content],
replace = Table.ReplaceValue(
Source,
0,
0,
(a, b, c) =>
let
f = (x) => Text.Contains(a, x),
y = try Number.From(a) otherwise a
in
if y is number and not Number.IsNaN(y) then
"Num"
else if f("A") then
"Upper"
else if f("B") then
"Middle"
else if f("C") then
"Lower"
else if f("NaN") then
""
else
a,
Table.ColumnNames(Source)
)
in
replace
Some comments:
Of course, you may use different list of columns in the last argument of the function.
The code may be simplified, if numbers are always as type text and/or may be only single version of "NaN".
If the replacement logic should be case-sensitive - adjust this line:
f = (x) => Text.Contains(a,x,Comparer.OrdinalIgnoreCase),
But since "NaN" contains "a" letter, some other code changes are required.

Related

How to match two columns of inexact text and return value in third?

I have to match two columns, one has "all_filenames" while the other has the "part_number".
I used VLOOKUP to find matches and it did work.
Under "all_filenames there is around 2,000 data and under "part_number" there are only 500.
The datas under "part_number" could match multiple datas under "all_filenames".
The problem is it does not match the specific name.
Example: Column A would be all_filenames:
XP605_Top.jpg
AR131_Front.jpg
28528_765BP_Front.jpg
2543_Front.jpg
On Column B would be "part_number":
XP605.jpg
AR131.jpg
28528.jpg
2543.jpg
This should be considered a match but since there are a few words or number missing from Column A it won't match.
I want to solve this with a UDF.
Public Function WhereIs(rIn As Range, rList As Range) As String
Dim s1 As String, r As Range
Dim s2 As String
WhereIs = ""
s1 = rIn.Text
For Each r In rList
s2 = r.Text
If InStr(1, s2, s1) > 0 Then
If WhereIs = "" Then
WhereIs = r.Address(0, 0)
Else
WhereIs = WhereIs & "," & r.Address(0, 0)
End If
End If
Next r
If WhereI <> "" Then WhereIs = "no match"
End Function
This is the only code I've found. It does not match because I think it tries to look for an exact match.
I need the 'match value' to return in another column with the part number and if there are multiple matches I need all of it to be in the column.
You could just use LEFT and FIND to clean up your columns of data. If your filenames are in column A then
=LEFT(A1,FIND("_",A1)-1)
Will remove everything up to the first "_".
For your parts list
=LEFT(C1,LEN(C1)-4)
will get rid of the ".jpg" portion of the name (or you could use REPLACE as suggested in the comments). This will make the VLOOKUP function happier

EXCEL Evaluate function inconsistent result

I have one data worksheet which is as per below format (100+ cols)
then I have another file containing some rules (multiple rules for each column in data file). I formulated vba conditions for every rule; for example, one rule was to check column A of data file should have only BP or Trip value for all rows (50K+ rows). So I translated that to below VBA
DataWB.Worksheets(1).Cells(J,X) = "BP" OR DataWB.Worksheets(1).Cells(J,X) = "Trip"
validate button code
f = Trim(ThisWorkbook.Worksheets(1).Cells(2, 3))
f = Replace(f, "J", 2)
f = Replace(f, "X", 1)
Debug.Print Application.Evaluate(f)
now problem is that evaluate throws type mismatch and if I use CBOOL it always return TRUE. I tried different variations too (like adding = or ? prefix) but nothing seem working. Any help will be highly appreciated.
Evaluate cant understand VBA Code rather excel worksheet formula can only be used, so i replaced with formula as in picture and it works perfectly now
For J = 2 To lRow
For x = 2 To 26
f = Trim(ThisWorkbook.Worksheets(1).Cells(x, 3))
f = Replace(f, "WB", SourceWB.Name)
f = Replace(f, "WS", SourceWB.Worksheets(1).Name)
f = Replace(f, "R#", J)
test = Evaluate(f)
If Not test Then Call LogError(J, x)
Next x
Next J

How to use "contains" function in VBA?

This is my Excel table with 3 input columns. The last column is the output column with the result I need.
Excel Input and Output data
Here is the sample macro I have:
Function month(x As string, y As string, z As String) As String
If (((x = "January.Winter") Or (y = "January.Winter")) And (z = "jan")) Then
month= "true"
Else If (((x = "January.2016") Or (y = "January.2016")) And (z = "jan")) Then
month= "true"
Else If (((x = "January.today") Or (y = "January.today")) And (z = "jan")) Then
month= "true"
Else
month= False
End If
End Function
My worksheet contains thousands of rows which includes "january" as a substring as a text in the cells. Instead of writing multiple checks like "if "x=January.winter"", I would like to use simplify the macro by checking if the string "x" or string "y" contains the string "January". Is there a way I could change the macro to do that?
Three ways that spring to mind:
If LCase$(x) Like "january*" Or LCase$(y) Like "january*" Then
...
If InStr(LCase$(x), "january") Or InStr(LCase$(x), "january") Then
...
If LCase$(Left$(x, 7)) = "january" Or LCase$(Left$(y, 7)) = "january" Then
...
It really just depends how inventive you want to get.
Note that I've used LCase$() to force text to lower case and prevent any issues with capitilisation - always something worth thinking about when comparing strings.
You can use the InStr function. Example use:
If (InStr(x,"January") > 0 Or InStr(y,"January")>0) And (z = "Jan") Then
...
It returns 0 if your substring isn't found, otherwise it returns the position of your substring.
More info here
Also careful with upper and lower casing. "January" will not match "january". Use LCase and UCase functions to force upper or lower casing, as Macro Man did in his answer.

Compare one string to all elements of an array

How do I get the result when '#' exist in the string will return 1 else 0. Now, I get the results of 0 0, although second string contain the character of '#'.
A = {'#'};
B = {'http://www.mathworks.com/help/matlab/ref/strcmpi.html',
'http://www.mathworks.com/help/matlab/ref/strcmpi#dfvfv.html'};
match = strcmpi(A,B)
Output:
match =
0
0
Desire Output
match =
0
1
Edit2:
why do i use the same concept as above but i get the wrong results? I want to check whether the file that store in 'data14' got 'javascript' & 'disableclick' at the same time. But the results return me all '1'.
for i = 1:4
A14 = {'javascript'};
B14 = {'disableclick'};
data14 = importdata(strcat('f14data/f14_data', int2str(i)));
feature14_data=any(cellfun(#(n) isempty(n), strfind(data14, A14{1}))) & any(cellfun(#(n) isempty(n), strfind(data14, B14{1})))
feature14(i)=feature14_data
end
This can be used to get desired output:
cellfun(#(n) ~isempty(n), strfind(B, A{1}))
You could use ismember iteratively:
cellfun(#(x)ismember('#',x), B)

Is it possible to concatenate a string with series of number?

I have a string (eg. 'STA') and I want to make a cell array that will be a concatenation of my sting with a numbers from 1 to X.
I want the code to do something like the fore loop here below:
for i = 1:Num
a = [{a} {strcat('STA',num2str(i))}]
end
I want the end results to be in the form of {<1xNum cell>}
a = 'STA1' 'STA2' 'STA3' ...
(I want to set this to a uitable in the ColumnFormat array)
ColumnFormat = {{a},... % 1
'numeric',... % 2
'numeric'}; % 3
I'm not sure about starting with STA1, but this should get you a list that starts with STA (from which I guess you could remove the first entry).
N = 5;
[X{1:N+1}] = deal('STA');
a = genvarname(X);
a = a(2:end);
You can do it with combination of NUM2STR (converts numbers to strings), CELLSTR (converts strings to cell array), STRTRIM (removes extra spaces)and STRCAT (combines with another string) functions.
You need (:) to make sure the numeric vector is column.
x = 1:Num;
a = strcat( 'STA', strtrim( cellstr( num2str(x(:)) ) ) );
As an alternative for matrix with more dimensions I have this helper function:
function c = num2cellstr(xx, varargin)
%Converts matrix of numeric data to cell array of strings
c = cellfun(#(x) num2str(x,varargin{:}), num2cell(xx), 'UniformOutput', false);
Try this:
N = 10;
a = cell(1,N);
for i = 1:N
a(i) = {['STA',num2str(i)]};
end

Resources