How to Query Large Sharepoint 2013 Lists in Infopath 2010? - list

I'm designing an Infopath form to help guide people in a data creation process. The form needs to draw from a Sharepoint list that contains around 19,000 rows, each with six columns that contain attributes (Column 1 = Attribute A, Column 2 = Attribute B, etc.) I've reduced the first three columns to their own lists, which contain only a few hundred unique entries each, if that. When I get to Column 4, there are 8,000 unique entries, which makes querying the list outright impossible
In an attempt to get around the item limitation, I've created an Infopath form with a data connection to the list (which does not automatically query when the form is loaded). Additionally, I've added drop downs that sets values for the queryFields of the secondary data source (one for Column 1, another for Column 2, and another for Column 3). On the last drop down, I set an action to query the database, but I still get the error regarding limitations and that rules cannot be applied.
Is there any way to "pre-filter" the data connection so that I can bypass the limitation by only drawing the data I need? Am I going about this the right way?
Any guidance would be greatly appreciated.

Are you able to add indexes to your list columns that you intend to query on? I've found that I can get around the error message on list limits if I go to the list and add an index for the columns that I will be setting as query fields prior to running my query data connection.

Related

POWER QUERY [Expression.Error] Cannot convert the value null to type Table

SOLVED USING A DIFFERENT APPROACH (see at the end)
I am trying to combine some queries into one by using the Table.Combine() function.
If I explicitly write the name of each query (e. g., Table.Combine({#"Name of query 1", #"Name of query 2"})) and then apply the changes, everything works fine.
However, since I want to make it dynamic, instead of writing a list of names, I pass the function a list of tables generated in a previous step:
So after I get this table, the next step is: = Table.Combine(PreviousStep[Value]). Note that Value is the name of the column that contains the tables. Apparently, by doing so this column of a table containing tables is converted to a list containing tables. This works fine (I can preview the resultset) until I hit that Apply changes button. When I do it, this message pops up:
I had a look at these threads: https://community.powerbi.com/t5/Desktop/We-cannot-convert-the-value-null-to-type-Table/td-p/391064, https://community.powerbi.com/t5/Desktop/We-cannot-convert-the-value-null-to-type-table/m-p/346056, but it didn't work. I've tried other approaches as well.
Further information:
Power BI Desktop version: 2.106.582.0 64-bit (June 2022)
Data source: combining existing queries that come from a single Excel file.
Steps followed to get that list of tables that I pass the Table.Combine() function:
let
Origen = #sections[Section1],
#"Convertido en tabla" = Record.ToTable(Origen),
#"Errores quitados" = Table.RemoveRowsWithErrors(#"Convertido en tabla", {"Value"}),
Personalizado1 = Table.SelectRows(#"Errores quitados", each Text.StartsWith([Name], "COMPRAS Y GASTOS")),
Personalizado2 = Table.Combine(Personalizado1[Value])
in
Personalizado2
I access all the queries I have (with the #sections keyword), convert it to a table, remove possible errors, filter to get the queries I want (the ones starting by "COMPRAS Y GASTOS") and then try to combine the queries).
A DIFFERENT APPROACH
What I wanted to do was merge tables that came from an Excel file, each of them referring to a year (2019, 2020, 2021, 2022). But I also wanted the combined table to update when new sheets were added on Excel (2023, 2024...).
I've tried many different approaches, like generating a dynamic list (from 2019 until the current year)... but for some reason none of them worked, even though the code apparently is correct.
So my new approach has been to create a sufficient amount of Excel sheets for the coming years (that are now empty, but when the new year comes the information will be filled in there), to create the queries referring to those sheets (they return empty tables) and merging those existing (but empty) tables with the ones from 2019-2022. This way, when data from 2023 is filled in in the sheet, the query is updated and it works.
It's a shame I couldn't actually solve the original problem I had, but this approach works.

Mapping user spreadsheet columns to database fields

I’m not sure where to start on this project. I know how to read the contents of the excel spreadsheet, I know how to identify the header row, I know how to loop over the contents. I believe I have the UX portion worked out but I am not sure how to process the data.
I’ve googled and only found .Net solutions but I’m looking for a ColdFusion/Lucee solution.
I have a working form allowing me to map a user's spreasheet column to my database values (this is being kept simple for this post; user does not have direct access to the database).
Now that I have my data, I'm not sure how to loop over the data results. I believe there will be several loops (an outer and an inner). Then of course I also need to loop over the file contents but I think if I can get the headings mapped out,I can figure out the remaining.
Any good links, tutorials, or guides would be greatly appreciated.
Some pseudo code might be enough to get me started.
User uploads form
System reads headers and content.
User is presented form with a list of columns from their uploaded spreadsheet to match with available database fields (eg “column1” matches “customer name”.
User submits form.
Now what?
UPDATED
Here is what the data looks like AFTER the mapping has been done in my form. The column deliiter is the ::: and within the column the ||| indicates the ID associated with the selected column value. I've included the id and the column value since I plan on displaying the mapping again as a confirmation. Having the ID saves a trip to the database.
If I understand correctly, your question is: how do you provide the user a form allowing them to map their spreadsheet columns to that of the database
Since you have their spreadsheet column names, and you have the database column names, then this problem is essentially a UI/UX problem. You need to show both lists, and allow the user to map them. I can imagine several approaches to this. My first thought would be some sort of drag/drop operation, as follows:
Create a list of boxes, one for each field in your database table, and include the field name in (or above) the box. I'll call this the db field list. Then, create another list for each column from the spreadsheet, which I'll call the spreadsheet column list. The user would drag/drop items from the spreadsheet column list to the db field list.
When a mapping has been completed by the user, you would store the column/field names in as data for the DOM element of the db field list box. Then upon submission, you would acquire the mapping data by visiting each box and adding it to an array. Then you would serialize that array into JSON and send that to your form submission handler.
This could be difficult or easy, depending on your knowledge of UI implementations using JavaScript. jQuery makes this easy (if you know jQuery). There's even a jquery UI plugin that does this: https://jqueryui.com/droppable/.
A quick search for javascript drag drop would help, and here's a few articles I found:
https://www.w3schools.com/html/html5_draganddrop.asp
https://medium.com/quick-code/simple-javascript-drag-drop-d044d8c5bed5
You would also need to submit the array of mappings using javascript. You could search for that as well, and here's an article I found:
https://codereview.stackexchange.com/questions/94493/submit-an-array-as-an-html-form-value-using-javascript

Fastest way to select several inserted rows

I have a table in a database which stores items. Each item has a unique ID, which the DB generates upon insertion (auto-increment).
A user may perform a specific task that will add X items to the database, however my program (C++ server application using MySQL connector) should return the IDs that the database generated right away. For example, if I add 6 items, the server must return 6 new unique IDs to the client.
What is the fastest/cleanest way to do such thing? So far I have been doing INSERT followed by SELECT for each new item OR INSERT followed by last_insert_id, however if there are 50 items to add it will take a few seconds at least which is not good at all for user experience.
sql_task.query("INSERT INTO `ItemDB` (`ItemName`, `Type`, `Time`) VALUES ('%s', '%d', '%d')", strName.c_str(), uiType, uiTime);
Getting the ID:
uint64_t item_id { sql_task.last_id() }; //This calls mysql_insert_id
I believe you need to rethink your design slightly. Let's use the analogy of a sales order. With a sales order (or invoice #) the user gets an invoice number (auto_incr) as well as multiple line item numbers (also auto_inc).
The sales order and all of the line items are selected for insert (from the GUI) and the inserts are performed. First, the sales order row is inserted and its id is saved in a variable for subsequent calls to insert the line items. But the line items are then just inserted without immediate return of their auto_inc id values. The application is merely returned the sales order number in the end. How your app uses that sales order number in subsequent calls is up to you. But it does not need to be immediate to retrieve all the X or 50 rows at once, as it has the sales order number iced and saved somewhere. Let's call that sales order number XYZ.
When you actually need the information, an example call could look like
select lineItemId
from lineItems
where salesOrderNumber=XYZ
order by lineItemId
You need to remember that in a multi-user system that there is no guarantee of receiving a contiguous block of numbers. Nor should it matter to you, as they are all attached appropriately with the correct sales order number.
Again, the above is just an analogy, used for illustration purposes.
That's a common but hard to solve problem. Unsure for mysql, but PostreSQL uses sequences to generate automatic ids. Inserting frameworks (object relationnal mappers) use that when they expect to insert many values: they query directly the sequence for a bunch of IDs and then insert new rows using those already known IDs. That way, no need for an additional query after each insert to get the ID.
The downside is that the relation ID - insertion time can be non monotonic when different writers intermix their inserts. It is not a problem for the database, but some (poorly written?) program could expect it is.
As you ID is autoincremental, you can do only two SELECT queries - before and after INSERT queries:
SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'dbTable' AND table_schema = DATABASE();
--
-- INSERT INTO dbTable... (one or many, does not matter);
--
SELECT LAST_INSERT_ID() AS lastID;
This will give you the siquence between first and last inserted IDs. Then you can easily calculate how many they are.

infopath form vlookup function based on sharepoint list BUT based on texboxes only (no dropdown)

I am fairly new to InfoPath and trying to create a form now that will link to the SharePoint list. Where I am stuck is that a lot of the steps online show you how to vlookup two fields (where one is a dropdown and another text box)But I need 2 fields to be a textbox field and connect them based on the sharepoint...so one text box field will automatically fill out info based on another Text box field..
So I have 2 infoPath fields:
a)Consumable Part number -> as a textbox - here user can manually enter the partnumber (I cant use dropdown here because we have circa 600 entries here!). All entries are stored in the sharepoint list in the Consumable Part Number column
b)Consumable Description -> as a textbox - here the field fills in automatically as soon as user enters the correct partnumber that indeed is available on this sharepoint list and each partnumber is linked to its unique Consumable Description. All entries are stored in the sharepoint list in the Consumable Part Number column
Is there anyway I could work around this please?
Thanks so much!
Add a data connection to the SharePoint List. Set the data connection to not run on form open - that is a checkbox in the last dialog box when you create the data connection.
On the text box where the user can enter a part number, add the following rules.
Rule condition - field bound to the text box for the user entered part number is not blank
Set a field's value - select the Part Number Query field from your SharePoint List data connection (be sure you pick the part number field in the "queryFields" folder)
Query for data - run the query to your SharePoint list
Set a field's value - set the field you want to have the description in to the returned data field Consumable Description in your SharePoint list data connection
Since you are querying based on the user entered part number, you should get back 0 or 1 item(s). You can add other rules to handle for the user entered number not being found (count of items returned in the SharePoint List data connection equals 0, you could display an error on the form, for example)
Edited to elaborate in light of additional comments:
The above technique sets a query field and returns items that match only that query field. If you have additional fields that dictate which list data should be returned, you'd set additional query fields.
If, instead, you need all items returned from the list and then you need to use XPath filters to determine which item you need from the list, you'd use the filter data button when picking the field that has the value you wish to use in your set value rule - from there you can add the various filters you need.
I'm afraid that I don't understand what you are attempting to achieve based on your comments.

Filter external list fields from client

BACKGROUND:
We’re developing a custom application which access SharePoint through the Client Object Model and this application need to access ECT (external content type) lists defined in SharePoint using the OM (Object Model). This application is a product that should be usable with most SharePoint installations and configuration and cannot have prior knowledge of External Lists.
When there are no filters set up for the ECT, SharePoint returns all the available items in the list (given the number is below the threshold). The moment we define a filter for this ECT, SharePoint return only the items after this filter is applied (probably correct behaviour from SP).
PROBLEM:
We need to be able to search this ECT list (non-filtered) based on text entered by a user in a search box. At the moment there seem to be no way to change the filter SharePoint applied when returning the values to the calling object.
I.e. I have 10 items in my ECT list (1,2,3…10). Each Item has 3 columns (ID, Name, Description). After setting up a filter for the ECT list, SharePoint return items 2, 3 & 6 when I ask SharePoint for a list of items.
No the user does a search the matches the description of item 7. How can I search/filter the list to return the item that match my search query?
I’ve been running in circles trying to solve this, but nothing seem to work. I tried setting the CAML query as well as the LoadQuery as defined in both http://pholpar.wordpress.com/2011/02/09/how-to-query-external-lists-on-the-client-side-using-caml/ and http://msdn.microsoft.com/en-us/library/ff464384.aspx but nothing seem to work.
Even I had this problem. Let me tell you there is no way of doing this.
Even in Server object model, there was an option to change the filters of the default view but then the SPList will return 0 items once the filter is applied.
The funny part is once your code runs & you open the list in SP UI, you can see the actual modified list. But the same cannot be queries in the object model.
Looks strange. I guess if you modify the SPList (ECT based) in this instance, then you can only get results in the next instance (like in next page refresh.....)