Find matching value in query based on text - excel

I am building a table in power query and I want to find the matching value from a column in a row. Does anyone know how to do this? I import my source data with:
leagueDataSource = #"League Data All",
this gives me this table:
I then have a variable called:
leagueName = "Albania - Superliga",
and want to create another variable called activeSeason. How do I match the variable leagueName with the value in active Season ?

Found the answer myself :)
leagueName = "name",
a = List.PositionOf(leagueDataSource[League], leagueName, 0),
leagueID = Number.ToText(leagueDataSource[Active Season]{a}),

Related

How does sibling or siblingAtRow() function works to retrieve the value from hidden Column in QTableWidget?

I have a database from which data is coming into a QTableWidget. The table in the database has the following Columns,
ID (Primary key, auto-increment value)
Name
Location
The QTableWidget has the following columns (that I have added)
ID (this column, I have hidden. and it contains the value of "ID" column from the Database Table)
Sr # (Represents the Row Number of the table)
Name (Contains "name" from the database table)
Location (Contains "Location from the database table)
Actions (Contains a Delete Button for that Row)
By hidden, I mean to say that I have made this column hidden using the folliwng command,
self.ui.table.setColumnHidden(0, True);
This is how I am populating my QTableWidget and creating a Delete Function,
def get_data(self):
mycursor = self.DB.cursor()
Subquery = "select id, name, location "
Subquery += " from tbl_person"
mycursor.execute(Subquery)
numcols = len(mycursor.fetchall()[0])
mycursor.execute(Subquery)
numrows = len(mycursor.fetchall())
self.ui.table.setRowCount(numrows)
self.ui.table.setColumnCount(numcols+2)
mycursor.execute(Subquery)
tablerow = 0
for row in mycursor.fetchall():
layout = QHBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
delete_button = QPushButton("Delete Data")
delete_button.clicked.connect(self.executeDeleteFunction)
# delete_button.setStyleSheet(delete_push_button) -> Only for styling
self.ui.table.setItem(tablerow, 0, PySide2.QtWidgets.QTableWidgetItem(str(row[0])))
self.ui.table.setItem(tablerow, 1, PySide2.QtWidgets.QTableWidgetItem(str(tablerow+1)))
self.ui.table.setItem(tablerow, 2, PySide2.QtWidgets.QTableWidgetItem(str(row[1])))
self.ui.table.setItem(tablerow, 3, PySide2.QtWidgets.QTableWidgetItem(str(row[2])))
self.ui.table.setCellWidget(tablerow, 4, delete_button)
tablerow += 1
self.ui.table.setColumnHidden(0, True)
#self.ui.registered_table.horizontalHeader().setSectionResizeMode(PySide2.QtWidgets.QHeaderView.Stretch)
self.ui.table.resizeColumnsToContents()
def executeDeleteFunction(self):
self.person_id = self.ui.table.selectionModel().selectedIndexes()[0]
self.person_id = self.person_id.row()
mycursor = self.DB.cursor()
sql = "delete from tbl_person where id = %s"
val = (id, )
mycursor.execute(sql, val)
print("Deletion Successful")
On the Deletion Function, what this code does is basically gets the value of the **Sr # ** Column from the QTableWidget and deletes the data according to that, i.e. it is getting me the value from the visible first column and not the actual first column. But, I want the data from the "ID" column of the QTableWidget which is hidden
I tried to look up on how to get the value from the first hidden column on the QTableWidget and ended up with this link: How to get data from hidden 'id' column in QtableWidget
This apparently solves my issue but I can not seem to make it work for my code. I don't want to retrieve values of multiple Rows but only of one row so how do I do this (as I am only deleting one row. But in the question mentioned, I believe that it is getting data from multiple rows due to that for each loop)?
Moreover, I tried to find help regarding the functionality of sibling function (which is provided in the answer of above question) however I could not find any good resource on this function (i.e. how to use this, or some practical example and etc.)
I tried the following with Sibling function to obtain the value of first hidden column of the Selected Row but it did not work,
self.value = self.table.selectedItems()[0]
self.value = sibling(self.value.row(), 0)
There are some conceptual problems with the given code.
First of all, the QtSql module should be preferred instead of artificially creating a model. For basic tables, QSqlTableModel is fine enough, while for custom queries, QSqlQueryModel is a good choice.
Now the problem is that UI-based selection is always based on visible items: if you select a row in a view that has hidden columns, you will not get the hidden indexes that belong to those columns.
In order to get the indexes (as in QModelIndex) of hidden columns on a table widget, the only way is the same for a table view: you need to access the model and get the index for the row, or you get the actual model index and then get the sibling (which is conceptually the same, as the underlying function does):
item = self.table.selectedItems()[0]
index = self.table.indexForItem(index)
firstRowIndex = index.sibling(index.row(), 0)
sqlIndex = firstRowIndex.data() # might be a string
Note that you can also use siblingAtColumn():
firstRowIndex = index.siblingAtColumn(0)
That's because when you create QTableWidget items, you're actually creating a new model, and the row for that model doesn't reflect the actual "row" of that index in the source model; items in the second row will return 1 for row(), even if their actual row is different, and that's because that item has been added as second to the table widget, since it's the second item in the query.
So, the solution is that you either get the incremental row value for the first column index sibling, or you use one of the predefined Sql models.
For simple models, the latter solution is fine enough, but if you need more complex models, the first is certainly more accurate and reliable.

Assigning Variable String Value to a table name

I am creating a table in a function, so the function outputs a table to the assigned variable name as shown below
[name] = tablefunc(input1, input2)
The thing is I want to be able to have the name be an input that was assigned earlier for example
name = 'dogs'
[something] = tablefunc(input1,input2)
I want to be able to put some code where it says something so that the outputted table for tablefunc is assigned the variable name dogs
It might be confusing why I am doing this but it is because I am extracting tables from a txt file in a for loop so I am getting lots of tables generated and I want to be able to give the tables their appropriate names as opposed to just table1, table2 etc.
That's not a good idea. As an alternative, you should create a structure:
function t = tablefunc(input1,input2)
t = table(input1,input2);
end
name = 'dogs';
s = struct();
s.(name) = tablefunc(rand(2),rand(2));
You can have one field per txt file.

Power Query (M) _ Dynamically update a column list for List.Sum function

I'm not sure if even possible but the goal is to dynamically update a query based on the user selecting a date. I have a table in my Excel file while updates a value which feeds to PeriodString variable (below)
/*Parameter name = PeriodString */
let
Source = Excel.CurrentWorkbook(){[Name="PeriodString"]}[Content],
StrPeriod = Source[Value]{0}
in
StrPeriod
The part of the code I want to update is the [ ..months selected ].
=List.Sum({[FYOpening],[January],[February],[March],[April],[May]})
With the below variable
=List.Sum({PeriodStr})
I tried using Table.Column as I realize I have to convert the value to a list of selectable columns but I cant' get it to work.
=List.Sum({Table.Column(PeriodString{0},PeriodString[0])})
Expression.Error: We cannot convert the value "[FY Opening],[Januar..." to type List.
Details:
Value=[FY Opening],[January],[February],[March],[April],[May]
Type=[Type]
Let me know if possible / alternatives.
If you need exactly value like "[Col1],[Col2],[Col3]" for PeriodString, then use such code:
let
Source = #table({"a".."e"},{{1..5}, {6..10}}),
PeriodString = "[b],[d],[e]",
sum = Table.AddColumn(Source, "sum", each List.Sum(Expression.Evaluate("{"&PeriodString&"}", [_=_])))
in
sum
I'd prefer to use PQ list instead:
let
Source = #table({"a".."e"},{{1..5}, {6..10}}),
list = {"b","d","e"},
sum = Table.AddColumn(Source, "sum", each List.Sum(Record.ToList(Record.SelectFields(_, list))))
in
sum

Power Query: Function to search a column for a list of keywords and return only rows with at least one match

I am making a simple Google-like search function in Power Query.
Let's say I have a column called Description in a table called Database. The user then inputs some search queries like "dog, cat, animals". I want to filter Database for rows that contain at least one of these keywords. They keywords can change each time, depending on what the user types in a named range in Excel.
I know you can filter a column in Power Query for multiple keywords, like this:
FilterRows = Table.SelectRows(LastStep, each Text.Contains([English], "dog") or Text.Contains([English], "cat")),
but those keywords are static, and the column is also static. I want to be able to control both the keywords and the column name as variables. I think I need to write a function but I am not sure how to start.
Your question requires several moving parts.
First, I would get the keywords from a named range "Keywords" into a table like this:
{KeywordTbl}
let
GetKeywords = if Excel.CurrentWorkbook(){[Name="Keywords"]}[Content]{0}[Column1] = null then null else Text.Split(Excel.CurrentWorkbook(){[Name="Keywords"]}[Content]{0}[Column1], ", "),
ConvertToTable = Table.FromList(GetKeywords,null,{"Keywords"})
in
ConvertToTable
Secondly, store the column name where you want to search in an Excel named range called "ColName". Then pull the named range into Power Query like this:
{ColName}
let
GetColName = Excel.CurrentWorkbook(){[Name="ColName"]}[Content]{0}[Column1]
in
GetColName
Then I would write a function that takes 4 variables, the table and column you want to look in, and the table and column containing the keywords:
{SearchColForKeywords}
(LookInTbl as table, KeywordTbl as table, LookInCol as text, KeywordCol as text) =>
let
RelativeMerge = Table.AddColumn(LookInTbl, "RelativeJoin",
(Earlier) => Table.SelectRows(KeywordTbl,
each Text.Contains(Record.Field(Earlier, LookInCol), Record.Field(_, KeywordCol), Comparer.OrdinalIgnoreCase))),
ExpandRelativeJoin = Table.ExpandTableColumn(RelativeMerge, "RelativeJoin", {KeywordCol}, {"Keywords found"}),
FilterRows = Table.SelectRows(ExpandRelativeJoin, each [Keywords found] <> null and [Keywords found] <> ""),
// Concatenate multiple keyword founds line into one line
GroupAllData = Table.Group(FilterRows, {"Word ID"}, {{"AllData", each _, type table [First column=text, Second column=text, ... your other columns=text]}}),
AddCol = Table.AddColumn(GroupAllData, "Keywords found", each [AllData][Keywords found]),
ExtractValues = Table.TransformColumns(AddCol, {"Keywords found", each Text.Combine(List.Transform(_, Text.From), ", "), type text}),
DeleteAllData = Table.RemoveColumns(ExtractValues,{"AllData"}),
MergeQueries = Table.NestedJoin(DeleteAllData, {"Word ID"}, FilterRows, {"Word ID"}, "DeleteAllData", JoinKind.LeftOuter),
ExpandCols = Table.ExpandTableColumn(MergeQueries, "DeleteAllData", {"First Col name", "Second col name", ... "Your Other column names here"}),
DeleteKeywordsFound = Table.RemoveColumns(ExpandCols,{"Keywords found"})
in
DeleteKeywordsFound
FYI, half of this function has been developed by a user named lmkeF on PowerBI community. The full discussion is here. I merely improved on his solution.
Finally, I will use that function in another query like this:
StepName = SearchColForKeywords(MainTbl, KeywordTbl, ColName, "Keywords"),
You may customize the 4 variable names.

Using string in place of property name (LINQ)

I have been able to get the values from tables using linq.
var q=(from app in context.Applicant
where app.ApplicantName=="")
Now what I want is this:
var q=(from app in context.Applicant
where app.stringIhave =="") // so instead of column name I have string which has same name as column.
Is it possible to specify string in Select as this is not sure what I will get in each case, I need different data all the time.
Is it possible to do so?
If no, then I will figure out something else.
Update
I have a GlobalString, which holds the column name of a table.
So when I query that table, I only specify from string which column value I want to get:
var q=(from app in context.Applicants
where app.ID==1013
select GlobalString //which is specifying that I want to get value from which column, as column name is not fixed.
//where GlobalString can have values like: app.FirstName..app.LastName etc
Update1:
var q = context.Applicants.Select("new(it.ApplicantFirstName as FirstName, it.ApplicantLastName as LastName)");
Error Message:
The query syntax is not valid. Near keyword 'AS'
You can use Dynamic Linq (available from NuGet) for that:
var q = context.Applicant.Where(app.stringIhave + " = #0", "");
for select you can try something like this
var q = context.Applicant.Select("new(it.FirstName as FirstName, it.LastName as LastName)");
so you only need construct string for that format

Resources