I've got a table full of different data types, including records, that I want to extract all column names of records to then use in an expand function. I've included a screenshot of a column containing record's however, when I use this = Table.ColumnsOfType(#"Expanded fields", {type record}), it returns an empty list .
I've tried looking through the entire column to see if there was anything different but its all record types. Any help please.
EDIT:
Error using Table.TransformColumnTypes
Record is not a valid type to search for. And judging by your image, your type is Type.Any as denoted by the ABC123
You best bet is to unpivot all the columns (perhaps those starting with a certain prefix) then on the new Value column, expand like so
#"PriorStepNameHere" = .... ,
ExpandList= List.Distinct(List.Combine(List.Transform(Table.Column(#"PriorStepNameHere", "Value"), each if _ is record then Record.FieldNames(_) else {}))),
Expand= Table.ExpandRecordColumn(#"PriorStepNameHere", "Value", ExpandList,ExpandList)
It sounds like the Table.ColumnsOfType function is not properly identifying the columns in your table that contain records.One possible reason for this is that the column's datatype is not properly set as 'record'. Another possible reason could be that the data in the columns is not structured properly and hence it is not being identified as a record. You can try to use the Table.TransformColumnTypes function to convert the column's datatype to 'record' and see if that resolves the issue.
If the issue still persists, please share the sample data and the code you are using.
I have a sheet with a list of company names in column A - some of these company names are present within sheets of different users, who have a tickbox within a column beside these companies.
I want to have a column in my sheet which would tell me whether this company is ticked within one of the user's sheets and if so, put the user's name in the cell next to it. If not, it can remain blank. The likelihood at this time that the tickbox is TRUE for the same company in two different sheets is negligible.
In the sample sheet below, I've used the following formula in cell B2:
=ifs(vlookup(A2,Sheet2!$A$2:$B$11,2,false)=TRUE,"Sam",vlookup(A2,Sheet3!$A$2:$B$11,2,false)=TRUE,"Nick",vlookup(A2,Sheet4!$A$2:$B$11,2,false)=TRUE,"Mike")
It works for the first two conditions, but then it cannot seem to work with the third logical pair. Note that the sample sheet below uses the vlookup across tabs, the actual sheet will be using importrange, but I don't think it should make a difference.
What could be wrong?
Sample sheet here
A More General Problem
To make this more general so others find it useful (which is the whole point of StackOverflow), the general problem can be rephrased as
"How do I search for a value in lists in multiple sheets, and return a
result if there is at least one match?"
Generally, when using VLOOKUP(), QUERY(), or other matching functions, you have to account for any errors through non-matches. Those "move" outwards into the outer functions and can eventually be the reported result, unless explicitly handled. Sometimes, this is less obvious when you sometimes get answers but that's because the outer functions have ignored or not evaluated the matching function.
Therefore, always consider what happens if the matching function returns a N/A and explicitly handle it.
Your Example
In your case, IFS() is simply raising an error whenever VLOOKUP() does not match. However, since IFS() returns the first condition that matches, from left to right in the formula, it doesn't always get around to evaluating one of the non-matching VLOOKUP()s which is why you see it works sometimes.
So, you should explicitly handle the errors with e.g. IFERROR()
My approach was to avoid lookup functions, and just filter the list by those that had filled checkboxes, and then count the occurrence of interest ("Company 1", "Company 2", ...) using COUNTIF(). If the counted total is 1, we have a match, so grab that entry as an element in an array. Otherwise, leave an empty value.
At this point, you could drop the empty elements, and take the first non-empty element (or return a blank), but I opted to list out all of the names.
To get rid of the blanks, I use QUERY() and then JOIN() to make a list of each name. In the case, where nothing matched, and my array was empty, I simply wrap everything in one IFERROR().
=IFERROR(JOIN(", ",QUERY(TRANSPOSE({IF(COUNTIF(FILTER(Sam!A:A,Sam!B:B=TRUE),A2)=1,"Sam",""),IF(COUNTIF(FILTER(Nick!A:A,Nick!B:B=TRUE),A2)=1,"Nick",""),IF(COUNTIF(FILTER(Mike!A:A,Mike!B:B=TRUE),A2)=1,"Mike","")}),"SELECT Col1 WHERE Col1 IS NOT NULL",0)),"")
I found it convenient for your example to rename "Sheet2" as "Sam", "Sheet3" as "Nick", "Sheet4" as "Mike", which is what I think was your original meaning.
The formula can be easily modified to show just the first matching result.
use:
=ARRAYFORMULA(IFNA(VLOOKUP(A2:A, QUERY({
QUERY(Sheet2!A2:B, "select A,B,'Sam'");
QUERY(Sheet3!A2:B, "select A,B,'Nick'");
QUERY(Sheet4!A2:B, "select A,B,'Mike'")},
"where Col2=TRUE"), 3, )))
I currently have a package pulling data from an excel file, but when pulling the data out I get rows I do not want. So I need to extract everything from the 'ID' field that has any sort of letter in it.
I need to be able to run a RegEx command such as "%[a-zA-Z]%" to pull out that data. But with the current limitation of conditional split it's not letting me do that. Any ideas on how this can be done?
At the core of the logic, you would use a Script Transformation as that's the only place you can access the regex.
You could simply a second column to your data flow, IDCleaned and that column would only contain cleaned values or a NULL. You could then use the Conditional Split to filter good rows vs bad. System.Text.RegularExpressions.Regex.Replace error in C# for SSIS
If you don't want to add another column, you can set your current ID column to be ReadWrite for the Script and then update in place. Perhaps adding a boolean column might make the Conditional Split logic easier at this point.
Say I have a query like the one below. What would be the best way to put each value into an array if I don't know how many results there will be? Normally I would do this with a loop, but I have no idea how many results there are. Would I need run another query to count the results first?
<CFQUERY name="alllocations" DATASOURCE="#DS#">
SELECT locationID
FROM tblProjectLocations
WHERE projectID = '#ProjectName#'
</CFQUERY>
Depending on what you want to do with the array, you can just refer to the column directly for most array operations, eg:
i = arrayLen(alllocations["locationID"]);
Using that notation will work for most array operations.
Note that this doesn't "create an array", it's simply a matter that a query columns - a coldfusion.sql.QueryColumn object is close enough to a CFML array for CF to be able to convert it to one when an array is needed. Hence the column can be passed to an array function.
What one cannot do is this:
myArray = q["locationID"];
This is because by default CF will treat q["locationID"] as a string if it can, and the string value is what's in the first row of the locationID column in the q query. It's only when an array is actually required will CF convert it to an array instead. This is basically how loose-typing works.
So if you just need to pass your query column to some function that expects an array, you can use the syntax above. If you want to actually put the column into a variable, then you will need to do something like this:
myArray = listToArray(valueList(q.localtionID));
NB: make sure you use <cfqueryparam> on your filter values instead of hard-coding them into your SQL statement.
myquery.column.toArray() is also a good undocumented choice.
Since you're only retrieving 1 field value from the query, you could use ValueList() to convert the query results into a comma-delimited list of locationIds, then use listToArray() to change that list into an array.
If you were retrieving multiple field values from the query, then you'd want to loop through the query, copy all the field values from the given row into a struct, and then add that struct to an array using arrayAppend().
(If you're not familiar with these functions, you can look them up in the Adobe docs or on cfquickdocs.com).
I'm trying to use SQL like select column from table where column in (?)
as ? should be concatenation of strings. I did script, that concatenates rows in something like 'string','secondstring' and so on.
I know, I should use just more parameters, but to the moment of execution I don't know, how many arguments there will be, and that is hundreds of them each time.
I'd like to do it in one SQL, so putting every argument in a single row, and check "execute for each row" isn't perfect either.
Any clue, how to do this?
You can use the cycles and variables kettle.
For example:
-create a job that contains:
1)a transformation where you store in an environment variable
(setVariable ("varname" value, "r") r is the parameter to be accessible by the parent job) the concat all input rows.
2)a transformation which makes the desired query with variable replacement (SELECT column FROM table WHERE column IN (${varname})).
If you need I can send the example files.