How can i write a function to update record in Microsoft Dynamic NAV using Role Tailored Client Report ?
Thx in advance,
Makara
You can place code in your report triggers.
Below is a simple example of code that can be put in the OnAfterGetRecord trigger of a Customer data item that refers to the Customer table.
IF Customer.Name[1] = 'A' THEN BEGIN
Customer.Name[1] := 'B';
Customer.MODIFY;
END
The code above changes the first character of the name of any customer included in the report that begins with an upper case 'A' to an upper case 'B'.
A complete report with just this functionality and no printout can be found from pastebin:
Simple Dynamics Nav Report Sample.
You can copy the entire content of the paste into a text file and import it into Nav as text.
Beware, however that doing this will replace any previous report with the id of 50000 with this example without any additional warning or prompt. The report imported as text will need to be saved in compiled form in Nav prior to you being able to run it.
You cannot place C/AL code directly on RTC Reports -- instead you should use the triggers behind DataItems in the 'Classic' client/Development Environment, as this code is common to both Classic and RTC reports, and executed when the report is run in either environment.
To use a similar example;
Vendor - OnAfterGetRecord()
----------------------------
...
IF Vendor."Phone No." = '' THEN BEGIN
Vendor."Phone No." := NewPhoneNo;
Vendor.MODIFY;
END;
...
You may want to set the following properties on the report itself to hide the print dialog, as well as the request form (assuming you don't want filters applied):
UseReqForm := FALSE;
ProcessingOnly := TRUE;
Another important thing to note is that code sitting behind sections is only used for Classic reports and won't be executed if running in the RTC (which may explain unexpected results).
Related
I'm building a PowerApps app on Azure SQL
The requirement
I have a form which has "Save" and "Confirm" buttons.
Both buttons should save the form data. The Commit button should also set database column "Confirm" to 1
I've read at length about how I can programatically override the update value of a hidden control for this. But I'm not satisfied with the level of complexity (maintenance) required to get this working, i.e.
Populate a variable with the current db value
In the button code set the variable value
In the form field, set the update property to the variable
What I'm Trying
So I'm trying a different approach: SubmitForm then Patch. Even though this requires an extra database call, I'd like to understand if this will work. This is the code for OnSelect in the commit button:
// Save the record
SubmitForm(frmEdit);
// Update confirmed to 1
Patch('[dbo].[Comments]',cRecord,{Confirmed:1});
Some Complexities
Note that my record is a variable, cRecord. In short I want this app to be able to upsert based on URL parameters.
This is my App.OnStart which captures URL values, inserts a record if required. Regardless, the result of this event is that cRecord is set to the record to be edited.
// Cache employees and store lookups (as they are in a different db)
Concurrent(Collect(cEmployees, Filter('[dbo].[SalesPerson]', Status = "A")),Collect(cStores, '[dbo].[Store]'));
// Check for parameters in the URL. If found, set to Edit/Add mode
Set(bURLRecord,If((!IsBlank(Param("PersonId")) && !IsBlank(Param("Date"))),true,false));
// If URL Parameters were passed, create the record if it doesn't exist
If(bURLRecord,
Set(pPersonId,Value(Param("PersonId")));
Set(pDate,DateValue(Param("Date")));
// Try and find the record
Set(cRecord,LookUp('[dbo].[Comments]',SalesPersonId=pPersonId && TransactionDate = pDate));
If(IsBlank(cRecord),
// If the record doesn't exist, create it with Patch and capture the resulting record
Set(cRecord,Patch('[dbo].[Comments]',Defaults('[dbo].[Comments]'),{SalesPersonId:pPersonId,TransactionDate:pDate}))
);
// Navigate to the data entry screen. This screen uses cRecord as its item
Navigate(scrEdit);
)
frmEdit.Item is set to cRecord. As an aside I also have a gallery that sets this variable value when clicked so we can also navigate here from a gallery.
The navigating using new and existing URL parameters works. Navigating from the gallery works.
The problem
When I press the Commit button against a record which has Confirmed=0 I get this popup error:
The data returned by the service is invalid
When I run this code against a record which already has Confirmed=1 I don't get an error
If I run the PowerApps monitor it doesn't show any errors but it does show some counts being run after the update. I can paste it here if required.
I also tried wrapping the Path in a Set in case it's result was confusing the button event but it didn't make a difference.
What I want
So can anyone offer me any of the following info:
How can I get more info about "The data returned by the service is invalid"?
How can I get this to run without erroring?
Is there a simpler way to do the initial upsert? I was hoping a function called Patch could upsert in one call but it seems it can't
With regards to the setting field beforehand approach, I'm happy to try this again but I had some issues implementing it - understanding which control where to edit.
Any assistance appreciated.
Edit
As per recommendations in the answer, I moved the patch code into OnSuccess
If(Confirmed=1,Patch('[dbo].[CoachingComments]',cRecord,{Confirmed:1}));
But now I get the same error there. Worse I cleared out OnSucces and just put SubmitForm(frmEdit); into the OnSelect event and it is saving data but still saying
The data returned by the service was invalid
First things first,
Refactoring has multiple steps,
I can t type all out at once...
The submitform and patch issue:
Never use the submitforn with extra conplexity
Submitform is only the trigger to send the form out,
The form handler will work with your data...
If you hsven t filled out the form correctly, u don t want to trigger your patch action...
So:
On your form, you have an OnSucces property,
Place your patch code there...
Change your cRecord in your patch statement:
YourForm.LastSubmit
I have found this tutorial for exporting context help ID values to a data file:
const
// Define the output file
OUTPUT_FILE = 'c:\tmp\topics.txt';
var
// Current topic ID
aTopicId: string;
// List of output
aList: TStringList;
begin
// Init list
aList := TStringList.Create;
aList.Add('Topic Caption | Help ID | Help Context');
aList.Add('--------------------------------------');
try
// Get first topic
aTopicId := HndTopics.GetTopicFirst();
// Loop through all topics
while aTopicId <> '' do
begin
// Add the topic to the list
aList.Add(Format('%s | %s | %d', [
HndTopics.GetTopicCaption(aTopicId),
HndTopics.GetTopicHelpId(aTopicId),
HndTopics.GetTopicHelpContext(aTopicId)
]));
// Get next topic
aTopicId := HndTopics.GetTopicNext(aTopicId);
end;
// Create the file
aList.SaveToFile(OUTPUT_FILE);
finally
aList.Free;
end;
end.
I have done some re-structuring of my revised help documentation and as a result the context numbers are not sequential:
Using HelpNDoc I was hoping to write a new API script to renumber them but I can't see a suitable API method.
Is this not possible?
Using HelpNDoc API, you can change the help context number of a topic using the HndTopics.SetTopicHelpContext method call. Using simple logic, it is possible to reset all help context numbers. This is described in the following article: Using HelpNDoc scripting capabilities to automatically reset all help context numbers
The script showcased in the article is even included in recent HelpNDoc's installation folder:
Context numbers can become messy as HelpNDoc project evolves. This script will reset each topic's context number so that they are setup incrementally from first topic till last one.
Here is how to run that script:
Save a backup of your project in case your need to go back
Load your project
From HelpNDoc's "Tools" ribbon tab, click "Script Editor"
Click the arrow next to "Load script" to display the list of built-in scripts
Click "ResetHelpContextNumbers.hnd.pas"
Click "Run script"
In a qlik report(Main Report) i have a text object with an action that open another report. Is there the possibility to show in the text object located in the Main Report the last Reloadtime date of the report that i open with the action ?
thank's
while reloading the other report,
use:
T1:
Load reloadtime() as reloadTime autogenerate(1);
store T1 into T1.qvd;
in the Main report file:
Load * from T1.qvd (qvd);
you can also use *add* Load * from T1.qvd (qvd); if you want to use partial reload.
thats it :)
i can use filetime() function but the last change is not necessarily the date of the last reloadtime().
I could store these information externally in a txt-file which you read in your target-application as include-variable. This will require a reload from the target. As alternatively could these value be stored in a database and read then per direct discovery without a reload.
A further option could be to transfer these information per selections by opening: AJAX and URL parameters maybe by selection a loosen dummy-date-table and these selection will then be queried per getfieldselections().
I'm trying to create functionality mentioned in the title. The idea that I have in mind is that I have a form, where I can select the server/-s (i have achieved that with a simple dialog list). So far I have this in my dialog list:
servers:=#Name([Abbreviate];#DbColumn(""; #If(#Subset(#DbName;1)="";"";#Subset(#DbName;1)) :"names.nsf";"($Servers)";1));
#Unique(#If(#IsError(servers);"";servers))
What I'm having problem is with selecting the databases available in the selected server/-s. Can anyone give me a hint on how to do this? Haven't really tried anything because I couldn't find the information.
Depending on your needs, it does not have to be that complicated: #Prompt has a special mode for picking a database:
result := #Prompt([ChooseDatabase];"";"");
FIELD Server := result[1];
FIELD Filename := result[2];
FIELD Title := result[3]
Using: Oracle ApEx 3.0.1
I have a SQL report region that contains a hidden page item as part of the "where clause". My problem is, based on a value entered by the user, I need to assign this value entered to my hidden item, so that it can be used within the where condition of my SQL but this would need to be done without actually submitting the form.
At the moment, I can set the value via an on-demand process but my SQL is still not returning any values as the hidden page item within the query is not set (as page has not been submitted).
I am not sure how to do this and whether in actual fact, this is possible to do, without having submitted the page.
Since you are on Apex 3, you don't have dynamic actions, but that doesn't hinder so much.
I've set up an example on apex.oracle.com. To get in the workspace, use workspace 'tompetrusbe' + apex_demo / demo.
There is a dynamic action there, which can do the work too, but i've disabled it.
What you need to make it work:
an ajax callback process, with the following line:
apex_util.set_session_state('P2_PAR_ENAME', apex_application.g_x01);
Give your report region a static id, i called mine 'report_emp'. This so i can easily retrieve it.
In the javascript region of the page, you then need to call the app process, and then refresh the region. Also bind the event which needs to trigger this action. I've done it here through the onchange event of the parameter textfield.
function refresh_report(oTrgEl){
//alert('refresh: ' + $v(oTrgEl));
//calling the application process which sets the session state of P2_PAR_ENAME
var oGet = new htmldb_Get(null, &APP_ID., 'APPLICATION_PROCESS=set_session_state', &APP_PAGE_ID.);
oGet.addParam("x01", $v(oTrgEl));
oGet.get(); //the app process just sets something, it returns nothing
//refresh the report region
$("#report_emp").trigger("apexrefresh");
};
function bind_events(){
//call this onload
$("#P2_PAR_ENAME").change(function(){refresh_report(this);});
};
In the query of the report i use where ename like '%'||UPPER(:P2_PAR_ENAME)||'%'.
When you type (for example) 'bl' in, and tab out (to trigger the onchange), the region will refresh and will be filtered.
You'll just need to adapt to your solution :)