I've written this code to generate a collection. I've tried to filter the collection using subsonic.where but its not working. Actually the where clause will change on user input so i cannot add the where clause to the sqlquery and also the datatable will be filled with different data from the collection based on the user input. How can I acheive this. Also i want the collection to be unchanged so that i use it further to filter with another where clause. Alo the I've selected only two columns but all columns are showing up. Please help.
Dim sq As SB.SqlQuery = New SB.Select("product.prodcode as 'Product Code'").From(DB.Product.Schema)
Dim wh As SB.Where = New SB.Where()
Dim prod As DB.ProductCollection = sq.ExecuteAsCollection(Of DB.ProductCollection)()
wh.ColumnName = DB.Product.ServiceColumn.PropertyName
wh.Comparison = SubSonic.Comparison.NotEquals
wh.ParameterValue = System.Decimal.One
Dim tab As DataTable = prod.Where(wh).Filter().ToDataTable()
Me.GridControl1.DataSource = tab
What you're doing doesn't make much sense - the where needs to go onto the query, then hit the DB - that's the way it should work. If you want to filter after the fact you can use Linq's Where(), which will filter the list for you.
Related
I have created a custom table and made it available on the Customers screen called 'Serial Tracking'. The purpose of this screen is to track serialised items that each customer is in possession of (regardless of who the item was purchased from).
I would like a record automatically added to the table on shipment release. I have attempted to customise the Release method of SoShipmentEntry but am having trouble getting all the required data together as well as the best way to structure the code.
The custom table DAC is
AUSerialTrack
Not necessarily the answer to your question but to long for a comment.
As an alternative, what if you set your Serials tab view to the Ship Line Split table without dealing with a custom table. You could get the information you needed with something like this: (need to convert to your BQL view for your serials tab)
SELECT [ship].[CustomerID],
[ship].[ShipmentNbr],
[split].[InventoryID],
[split].[LotSerialNbr]
FROM [dbo].[SOShipLineSplit] split
INNER JOIN [dbo].[SOShipLine] line
ON [line].[CompanyID] = [split].[CompanyID]
AND [line].[ShipmentNbr] = [split].[ShipmentNbr]
AND [line].[LineNbr] = [split].[LineNbr]
INNER JOIN [dbo].[SOShipment] ship
ON [ship].[CompanyID] = [split].[CompanyID]
AND [ship].[ShipmentNbr] = [split].[ShipmentNbr]
INNER JOIN [dbo].[InventoryItem] i
ON [i].[CompanyID] = [split].[CompanyID]
AND [i].[InventoryID] = [split].[InventoryID]
INNER JOIN [dbo].[INLotSerClass] c
ON [c].[CompanyID] = [i].[CompanyID]
AND [c].[LotSerClassID] = [i].[LotSerClassID]
WHERE [c].[LotSerTrack] = 'S'
AND [ship].[Confirmed] = 1;
Then when the user goes to the tab its always the current results. No custom code to fill in a custom table so easier for upgrades/customization maintenance.
I have not used LINQ very extensively, but I'm trying to read data from a large Excel spreadsheet (14K+ rows) that requires me to make queries from multiple worksheets and even requery the original spreadsheet to filter specific data. Because OleDb queries of Excel can take a relatively long time (500+ms per query for a file on my local machine), I'm doing a couple of these queries at the front of my method, starting a loop through a "base" DataTable, then trying to use LINQ to filter down the data within that loop to put the appropriate data into a more structured DataSet. Here is some code to help explain (VB.NET):
Dim Connection As System.Data.OleDb.OleDbConnection
Dim Command As System.Data.OleDb.OleDbDataAdapter
Dim EXCEL_SHEET_DATA_1 As New DataTable
Dim EXCEL_SHEET_DATA_2 As New DataTable
Dim EXCEL_SHEET_DATA_3 As New DataTable
Dim TapeFile As New FileInfo("C:\TempFolder\tapefile.xls")
Connection = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source='" & TapeFile.FullName & "'; Extended Properties=Excel 8.0;")
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET1$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_1)
Command.Dispose()
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET2$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_2)
Command.Dispose()
Command = New System.Data.OleDb.OleDbDataAdapter("SELECT * FROM [SHEET3$] ORDER BY [USER_ID] ASC, [MEMBER_NUMBER] ASC;", Connection)
Command.Fill(EXCEL_SHEET_DATA_3)
Command.Dispose()
For Each Row As DataRow In EXCEL_SHEET_DATA_1.Rows
Dim MemberNumber As String = Row("MEMBER_NUMBER").ToString.Trim
Dim UserNumber As String = Row("USER_ID").ToString.Trim
' -- CODE FOR INITIAL PROCESSING OF SHEET1 DATA - NO ERRORS --
Dim CoMemberQuery As IEnumerable(Of DataRow) = From cm In EXCEL_SHEET_DATA_2 Where cm("MEMBER_NUMBER") = MemberNumber And cm("USER_ID") = UserNumber
For Each CoMemberRow As DataRow In CoMemberQuery
' -- CODE FOR PROCESSING OF SHEET2 DATA - NO ERRORS --
Next CoMemberRow
Dim VehicleQuery As IEnumerable(Of DataRow) = From veh In EXCEL_SHEET_DATA_1 Where veh("MEMBER_NUMBER") = MemberNumber And veh("USER_ID") = UserNumber Order By veh("VIN") Ascending
' *******************************************************
' -->> HERE IS WHERE I *SOMETIMES* GET THE EXCEPTION <<--
' *******************************************************
For Each VehicleRow As DataRow In VehicleQuery
' -- CODE FOR SECONDARY PROCESSING OF SHEET1 DATA - NO ERRORS --
Next VehicleRow
Next Row
I don't get the exception every time. The only thing I've noticed as possibly having something to do with it is that for the specific MemberNumber and UserNumber combination that causes the first exception, the first row in the result set would most likely contain a NULL value for the VIN field.
I'm sure the problem has to do with my LINQ query syntax, but I am simply too inexperienced in this regard to know why it's failing. Any assistance would be greatly appreciated. If you require any additional information regarding the code or implementation, let me know and I'll try to add it to the question.
Thank you for your time.
Your VehicleQuery has the following phrase: Order By veh("VIN") Ascending.
So as soon as VehicleQuery gets evaluated (by starting the For loop), LINQ will evaluate all of the items in that query, and then perform a sorting operation, which involves comparing the veh("VIN") values with each other and putting them in order.
When comparing any two items in your query, it tries to see if either value knows how to compare itself with values of the other type (hence implementing the IComparable interface. If they cannot, then it doesn't know which one should go first.
My guess is that veh("VIN") is (sometimes) yielding objects that don't know how to compare themselves with other values returned by this expression. Depending on the kind of data you're using, and how you want it to be compared, you might consider doing some kind of cast or conversion, or simply calling ToString() on the value, to make sure it's comparable: Order By veh("VIN").ToString() Ascending
(Please pardon any syntax errors, as I'm a C# developer.)
Our Business Accounts in Acumatica have 13 custom Attributes for our main Business Account Class. I've been able to save values to the Attributes successfully, based on Acumatica's example "Adding Records to the Business Accounts and Opportunities Forms". But I have not been able to figure out how to retrieve the values with an Export.
First, I tried using a format similar to how the field was specified when saving them.
Public Function GetCustomerAttributes(ByVal customerID As String) As String()()
Dim customer As CR303000Content = m_context.CR303000GetSchema()
m_context.CR303000Clear()
Dim idFilter As Filter = New Filter()
idFilter.Field = customer.AccountSummary.BusinessAccount
idFilter.Condition = FilterCondition.Equals
idFilter.Value = customerID
' SIMILAR TO EXAMPLE FOR SAVING
Dim awdField As Field = New Field()
awdField.ObjectName = customer.Attributes.Attribute.ObjectName
awdField.FieldName = "AWD Number"
Dim searchfilters() As Filter = {idFilter}
Dim searchCommands() As Command = {awdField}
Dim searchResult As String()() = m_context.CR303000Export(searchCommands, searchfilters, 0, False, False)
Return searchResult
End Function
I thought this would return one result with the value for our attribute named "AWD Number". Instead, it returned 13 results, one for each attribute, and the value of each one was blank. I changed the FieldName to customer.Attributes.Attribute.FieldName and then it started returning the name of each attribute. So I thought if I added another field for the value, then I might get the name and value in separate results, like this:
Public Function GetCustomerAttributes(ByVal customerID As String) As String()()
Dim customer As CR303000Content = m_context.CR303000GetSchema()
m_context.CR303000Clear()
Dim idFilter As Filter = New Filter()
idFilter.Field = customer.AccountSummary.BusinessAccount
idFilter.Condition = FilterCondition.Equals
idFilter.Value = customerID
Dim awdField As Field = New Field()
awdField.ObjectName = customer.Attributes.Attribute.ObjectName
awdField.FieldName = customer.Attributes.Attribute.FieldName
Dim awdValue As Field = New Field()
awdValue.ObjectName = customer.Attributes.Attribute.ObjectName
awdValue.FieldName = customer.Attributes.Attribute.Value
Dim searchfilters() As Filter = {idFilter}
Dim searchCommands() As Command = {awdField, awdValue}
Dim searchResult As String()() = m_context.CR303000Export(searchCommands, searchfilters, 0, False, False)
Return searchResult
End Function
I did get a 2-item array back for each of the 13 results, but the value in the second field was still blank.
Does anyone know how I can get the values? I don't really care if I have to get them one at a time, but I'd prefer to get them all at once with their names or codes so that I don't have to rely on the indices always staying the same. Below are images of the debugger running on my second example and view in Acumatica. Thanks!
Your first attempt is correct, however you're not using the right object name and field name. The system will dynamically add fields to the primary object (view) of the screen, in this case the object name represented by customer.AccountSummary.BusinessAccount.ObjectName variable (I suggest you use the debugger to see what this value equals too - good learning exercise).
The attribute field name will use the same naming convention as used in How To Retrieve An Attribute Field In StockItems In Acumatica API?. The naming convention is _Attributes. The attribute ID is not the attribute name; I don't see your configuration but I doubt in your case the Attribute ID is "AWD Number". To summarize, the code will look like:
Dim awdField As Field = New Field()
awdField.ObjectName = customer.AccountSummary.BusinessAccount.ObjectName
awdField.FieldName = "AWDNumber_Attributes"
In your example, by putting the Attributes.Attribute.ObjectName object, the system will iterate through all values inside this table, and then return for every row the fields you want. I'm not exactly sure why you're not seeing all the attribute values in this case, but I think you should be fine with the example above.
I'm in Excel 2010 VBA, using ADO 2.8 to query an Access 2010 database. I don't own the database and don't have any authority to make any changes to it. I've been working with Excel VBA for many years but my Access knowledge is sketchy.
Using the same SQL as one of the queries in the database (copied from the Access query and pasted into Excel VBA), I get different results in some fields than that query in the database gets.
For the affected fields, I see that in Access those fields are defined as lookups. Here's an example lookup from one of the affected fields' Row Source property:
SELECT [Signers].[SignerID], [Signers].[SignerName] FROM Signers ORDER BY [SignerID], [SignerName];
In the Access database, where the SQL statement refers to that field, the query returns SignerName.
But in my ADO code, where the very same SQL statement refers to that field, the query returns SignerID, not SignerName.
Is there something I can do from my ADO code to get SignerName instead of SignerID, from the same SQL statement? Or do I need to modify the SQL statement?
Thanks,
Greg
Update:
On the Access side, I think I see now why only SignerName appears. On the field's Lookup tab, the Column Widths property is:
0";1.2605"
So I guess SignerID is there in the Access query result but with a column width of 0.
Unfortunately that doesn't help me on the ADO side. Any suggestions on getting SignerName instead of SignerID in the ADO query result?
Update2:
Here's a sample SQL statement that returns different fields depending on either it's in Access or in ADO:
SELECT MasterAccount.[SignerKey1]
FROM MasterAccount ;
Per Preet's request, here's the ADO code in Excel VBA:
strDatabasePath = rgDatabasePathCell.Value 'rgDatabasePathCell is a worksheet cell object.
strPWD = DATABASE_PASSWORD
Set cnn = New ADODB.Connection
cnn.Provider = "Microsoft.ACE.OLEDB.12.0"
cnn.ConnectionString = "Data Source='" & strDatabasePath & "';Jet OLEDB:Database Password='" & strPWD & "';"
cnn.Open
Set cmd = New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandType = adCmdText
cmd.CommandText = strSQL
Set rst = New ADODB.Recordset
rst.Open cmd.Execute
shMA.Cells(2, 1).CopyFromRecordset rst 'shMA is a worksheet object.
Update 3:
It occurred to me that from what I've said so far, it might seem like I could just change this:
SELECT MasterAccount.[SignerKey1]
FROM MasterAccount ;
to this:
SELECT [Signers].[SignerName]
FROM MasterAccount ;
But there are 13 affected lookup fields, all with exactly the same "Row Source" property text as shown above, and all return different SignerName items for each row. I don't know why they are all returning different items per row; I have not been able to find any difference in the way they are defined. I've been tasked with getting the same result in Excel as that Access query gets.
Update 4:
VBlades -- Thanks, I found the form that has a tab with dropdowns for each of the 13 SignerKey-n fields. If I right-click that form and choose Form Properties, the RecordSource property is:
SELECT MasterAccount.*, Bank.BankRating FROM Bank INNER JOIN MasterAccount ON Bank.BankID = MasterAccount.Bank;
However I don't understand how that would be selecting a different SignerName item for each of the 13 SignerKey-n fields, or what to do with this information to get the same results in ADO as in the Access query. Any suggestions?
Update 5:
I may be close to a workaround. If I do this, I get the SignerName field for SignerKey1:
SELECT Signers.SignerName
FROM Signers RIGHT JOIN MasterAccount ON Signers.SignerID = MasterAccount.SignerKey1.Value;
And if I do this, I get different SignerName items for each field on each row:
SELECT Signers.SignerName, Signers_1.SignerName, Signers_2.SignerName
FROM Signers AS Signers_2 INNER JOIN (Signers AS Signers_1 INNER JOIN (Signers RIGHT JOIN MasterAccount ON Signers.SignerID = MasterAccount.SignerKey1.Value) ON Signers_1.SignerID = MasterAccount.SignerKey2.Value) ON Signers_2.SignerID = MasterAccount.SignerKey3;
That works both in an Access query and in ADO. Next step, I'll try to add these joins to the main SQL statement.
Update 6:
Well, when I try to add even one of those 13 joins to the main SQL statement, it works fine in an Access query, but in ADO I get the error:
Row handles must all be released before new ones can be obtained.
So I'm stuck. Any suggestions?
I've raised the issue with the database owner, but they don't know why the affected fields' Row Source property includes SignerID, so I'm not sure if that's going to help.
You can do the following (simplest way)
Exclude [Signers].[SignerID] from the Query
SELECT [Signers].[SignerName] FROM Signers ORDER BY [SignerID], [SignerName];
Or, create Composite field containing both [SignerID], [SignerName] and extract any part using VBA that you are familiar with:
SELECT ([SignerID] & "_" & [SignerName]) As Composite FROM Signers ORDER BY [SignerID], [SignerName]
Regards,
Okay, I worked around the problem by getting a separate recordset of the SignerID and SignerName fields from the Signers table.
Then I looped through all the rows of each affected field, looked up SignerID in the 2nd table, and swapped in SignerName for SignerID in the original table.
I tried to do that in ADO, but got the error "An UPDATE or DELETE query cannot contain a multi-valued field". So instead I made the swaps after copying the recordset to the Excel worksheet.
I would have liked to know how to handle it all in ADO, but this works. All is well now.
I retrieve names from a group using formula, and put them in a field of type Names this way:
#Name([CN];NAME)
I want to manipulate this data in my code, but using Lotusscript. Can't find it at Google or Lotus Domino's Help. Is there a way I can handle this?
In LotusScript there is a class named "NotesName" to do such manipulations.
If there is a field named "NAME" in you document, then the code would look like:
Dim doc as NotesDocument
Dim nnName as NotesName
'Somehow get the document, using ws.CurrentDocument.document
'or db.UnprocessedDocments.GetFirstDocument, depends on your situation
Set nnName = New NotesName( doc.GetItemValue("NAME")(0) )
Whatyourlookingfor = nnName.Common
If NAME is a Multivalue then you would have to write a loop to get the common- name for every element in the array doc.GetItemValue("NAME")
The next time you have a question, check out the language cross reference in the help...
There it tells you, what the LotusScript- Pendant for #Name is.
Please try with below suggestion for getting list of person names from group.
First need to check the availability of searching group on names.nsf (All the groups are available on "($VIMGroups)" view.
if the group is available means you need to get the list of values from "Members" item
The members item have variant(list) values. So need to iterate the members for getting each value
Please refer the below sample code:
Set namesDb=session.GetDatabase(db.Server,"names.nsf")
Set groupVw=namesDb.GetView("($VIMGroups)")
Set groupDoc=groupvw.GetDocumentByKey("groupname")
persons= groupDoc.members
Forall person In persons
Msgbox person
End Forall
You can use the Evaluate method. It will return you the result of a Notes Formula:
Dim result as Variant
formula$ = "#Name([CN];NAME)"
result = Evaluate(formula$)
If the formula needs to be evaluated within the context of a document, you can pass that document as a second parameter to the method.
More info here