This row:
intersection(CurrentZplaneTransRegion, Unshifted, CurrentRegion)
sometimes returns a empty region. I need to catch this situation. How can I verify if the currentRegion is empty?
There are 2 possibilities for this.
First:
area_center (CurrentRegion, AreaCurrentRegion, _, _)
if (AreaCurrentRegion==0)
* CurrentRegion is empty
else
* CurrentRegion is not empty
endif
Second:
gen_empty_region (EmptyRegion)
if (CurrentRegion==EmptyRegion)
* CurrentRegionn is empty
else
* CurrentRegion is not empty
endif
You can use the operator area_center(CurrentRegion, Area, Row, Column) for this and check the Area result if it is zero.
Related
=IF(B12<>"",(IF(U12="Subscription","Subscribe",IF(U12="T.E.H.","Subscribe",IF(U12="ESA","Subscribe",IF(U12="Perpetual","Buy",IF(U12=" "," ")))))))
I get a "False" value in the cell with this formula in it when the value in U12 is not one of the options and I want to get a blank
Appreciate any help
Thanks
Change this: IF(U12=" ", " ") to this: IF(U12=" ", " ", ""). Here's a demo in Google Sheets, but the formulas are the same.
https://docs.google.com/spreadsheets/d/10iFqq0PNt9VhGKMPLCxsI1df0x4nDSxCaCGSdEEktO8/edit#gid=0
However, I don't think this is exactly right. For one thing, it looks like this clause:
IF(U12=" ", " ")
is only there to try to generate the blank you are looking for. If that's the case, then change it to:
IF(U12=" ", " ", "")
However, I think I would probably use some array constants, something like this:
=IF(B12<>"", CHOOSE(SUM(--(U12={"Subscription","T.E.H","ESA"})) + IF(U12="Perpetual", 2) +1, "", "Subscribe", "Buy"))
To break this down a little, let me reformat so it's easier to see:
=IF(
B12 <> "",
CHOOSE(
SUM(--(U12={"Subscription","T.E.H","ESA"})) +
IF(U12="Perpetual", 2) + 1
"", "Subscribe", "Buy"
)
)
I'm going to use CHOOSE, which takes an index number N and a list of choices, and it returns the Nth element in the choice list. To generate the index, I'm going to use a couple of techniques. First look at this:
U12 = {"Subscription", "T.E.H", "ESA"})
This is going to test U12 against all of the choices in the list, and return an array of TRUE/FALSE values. If U12 matches any of the elements in the array constant, then one of those values will be TRUE. We use -- to coerce that array from TRUE/FALSE to 0/1, and then we use SUM to get the array into a single value. It will either be 0 if U12 doesn't match any of the options, or 1 if it does.
Then I'm going to use a standard IF to check if U12 = Perpetual, and return 2 if it does. Adding that result to the previous sum will give us a final number that is either 0, 1 or 2.
CHOOSE is 1 indexed, meaning that it expects the index to be 1 or greater, so we add 1 to the number we just generated and pass it to CHOOSE along with a list of options.
The advantage here is that if the Subscribe options change you can just change the list, instead of having to alter a bunch of nested IFs. Also, if you need to support multiple buy options, you can do it with a similar construction:
SUM(--(U12 = {"Subscription", "T.E.H", "ESA"})) +
IF(SUM(--(U12 = {"Perpetual", "Buy Now"})), 2) + 1
and if you needed to add return values just keep extending:
CHOOSE(
SUM(--(U12 = {"Subscription", "T.E.H", "ESA"})) +
IF(SUM(--(U12 = {"Perpetual", "Buy Now"})), 2) +
IF(SUM(--(U12 = {"Release", "Dropping"})), 3) + 1,
"", "Subscribe", "Buy", "Sell"
)
If you think this is something that might need to be maintained or the options might change, I would set it up like this, as opposed to nested IFs.
Is this a little clearer?
=IF(B12=""," ",IfError(VLookup(U12,{"ESA","Subscribe";"Perpetual","Buy";"Subscription",Subscribe";"T.E.H.","Subscribe"},2,false)," "))
This is really just a table lookup, hence the use of VLookup. The lookup array is a two dimensional array in curly brackets - the commas and semicolons are very important for defining a 2x4 array for VLookup. The IFError function tells how to return your desired " " result if the lookup fails.
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.
I've been trying to find a way to remove a string from a table kind of like this:
myTable = {'string1', 'string2'}
table.remove(myTable, 'string1')
but I haven't been able to find anyway to do it. Can someone help?
As hjpotter92 said, table.remove expects the position you want removed and not the value so you will have to search. The function below searches for the position of value and uses table.remove to ensure that the table will remain a valid sequence.
function removeFirst(tbl, val)
for i, v in ipairs(tbl) do
if v == val then
return table.remove(tbl, i)
end
end
end
removeFirst(myTable, 'string1')
table.remove accepts the position of an element as its second argument. If you're sure that string1 appears at the first index/position; you can use:
table.remove(myTable, 1)
alternatively, you have to use a loop:
for k, v in pairs(myTable) do -- ipairs can also be used instead of pairs
if v == 'string1' then
myTable[k] = nil
break
end
end
I would like to pass the arguments to the function of two ways, as the Sum function in Excel does. eg. = SUM (A1, B1, C1) or SUM (A1: C1).
Either way, separately, I know.
1) Calc (double fstNum, double secNum, double thdNum, double fthNum)
2) Calc (xl_array p_array *)
Any help will be appreciated.
Thanks.
One possible way would be using the xloper12 type and check if the parameter is of type array, single value or empty.
*calc (xloper12* arg1, xloper12* arg2, xloper12* arg3){
double sum = 0;
// check first arg if empty
if (!(arg1->xltype & (arg1| xltypeNil))){
// check if arg is array
if ( arg1->xltype == xltypeMulti){
// for loop - summing the array values
}
// single value
else {
sum += arg1->val.num;
}
}
// check next arg and do the same
...
It may help to think of SUM(...) as operating on ranges of cells:
SUM(Rg1, Rg2, Rg3, ... )
Then your two examples are: (a) 3 ranges of 1 cell each, and (b) 1 range of 3 cells.
[ In response to uncommented downvote. ]
Try
3) Calc (xl_array p_array1 *, xl_array p_array2 *, xl_array p_array3 *, xl_array p_array4 *)
Nothing (of course!) that these arrays can be 2 dimensional.
I have a table with 2 columns. In column 1, I have a string information, in column 2, I have a logical index
%% Tables and their use
T={'A2P3';'A2P3';'A2P3';'A2P3 with (extra1)';'A2P3 with (extra1) and (extra 2)';'A2P3 with (extra1)';'B2P3';'B2P3';'B2P3';'B2P3 with (extra 1)';'A2P3'};
a={1 1 0 1 1 0 1 1 0 1 1 }
T(:,2)=num2cell(1);
T(3,2)=num2cell(0);
T(6,2)=num2cell(0);
T(9,2)=num2cell(0);
T=table(T(:,1),T(:,2));
class(T.Var1);
class(T.Var2);
T.Var1=categorical(T.Var1)
T.Var2=cell2mat(T.Var2)
class(T.Var1);
class(T.Var2);
if T.Var1=='A2P3' & T.Var2==1
disp 'go on'
else
disp 'change something'
end
UPDATES:
I will update this section as soon as I know how to copy my workspace into a code format
** still don't know how to do that but here it goes
*** why working with tables is a double edged sword (but still cool): I have to be very aware of the class inside the table to refer to it in an if else construct, here I had to convert two columns to categorical and to double from cell to make it work...
Here is what my data looks like:
I want to have this:
if T.Var1=='A2P3*************************' & T.Var2==1
disp 'go on'
else
disp 'change something'
end
I manage to tell matlab to do as i wish, but the whole point of this post is: how do i tell matlab to ignore what comes after A2P3 in the string, where the string length is variable? because otherwise it would be very tiring to look up every single piece of string information left on A2P3 (and on B2P3 etc) just to say thay.
How do I do that?
Assuming you are working with T (cell array) as listed in your code, you may use this code to detect the successful matches -
%%// Slightly different than yours
T={'A2P3';'NotA2P3';'A2P3';'A2P3 with (extra1)';'A2P3 with (extra1) and (extra 2)';'A2P3 with (extra1)';'B2P3';'B2P3';'NotA2P3';'B2P3 with (extra 1)';'A2P3'};
a={1 1 0 1 1 0 1 1 0 1 1 }
T(:,2)=num2cell(1);
T(3,2)=num2cell(0);
T(6,2)=num2cell(0);
T(9,2)=num2cell(0);
%%// Get the comparison results
col1_comps = ismember(char(T(:,1)),'A2P3') | ismember(char(T(:,1)),'B2P3');
comparisons = ismember(col1_comps(:,1:4),[1 1 1 1],'rows').*cell2mat(T(:,2))
One quick solution would be to make a function that takes 2 strings and checks whether the first one starts with the second one.
Later Edit:
The function will look like this:
for i = 0, i < second string's length, i = i + 1
if the first string's character at index i doesn't equal the second string's character at index i
return false
after the for, return true
This assuming the second character's lenght is always smaller the first's. Otherwise, return the function with the arguments swapped.