giovedì 2 aprile 2020
lunedì 16 marzo 2020
D365 FFO - lookup su formcontrol unbound
Questo link mostra come fare la lookup via CoC sul campo di un datasource:
https://community.dynamics.com/365/financeandoperations/f/dynamics-365-for-finance-and-operations-forum/357208/lookup-on-form-datasource-field
Per fare la lookup su un controllo unbound dobbiamo fare così:
In questo modo invece possiamo effettuare la CoC sul metodo clicked di un pulsante:
https://community.dynamics.com/365/financeandoperations/f/dynamics-365-for-finance-and-operations-forum/357208/lookup-on-form-datasource-field
Per fare la lookup su un controllo unbound dobbiamo fare così:
[ExtensionOf(formControlStr(ProjTableWizard,FormControl))]
final class LILProjTableWizard_Extension
{
public void lookup()
{
next lookup();
Query query = new Query();
query.addDataSource(tableNum(CustGroup));
SysTableLookup sysTableLookup = SysTableLookup::newParameters(tableNum(CustGroup),this);
systableLookup.addLookupfield(fieldNum(CustGroup, CustGroup), true);
systableLookup.addLookupfield(fieldNum(CustGroup, Name), false);
sysTableLookup.parmQuery(query);
sysTableLookup.performFormLookup();
}
}
In questo modo invece possiamo effettuare la CoC sul metodo clicked di un pulsante:
[ExtensionOf(formControlStr(WHSShipPlanningListPage,Transfer))]
final class MCSWHSShipPlanningListPageTransfer_Extension
{
void clicked()
{
FormDataSource WHSShipmentTableDS;
FormControl control = this as FormControl;
WHSShipmentTableDS = control.formRun().dataSource(formDataSourceStr(WHSShipPlanningListPage,WHSShipmentTable)) as FormDataSource;
next clicked();
WHSShipmentTableDS.research(true);
}
}
domenica 1 marzo 2020
D365FFO - Cercare l'id dell'etichetta in base al testo
In questo post vediamo un job (runnableClass) per cercare il codice dell'etichetta in base al testo. Nel esempio vogliamo cercare tutte le etichette che contengono "Data Fattura":
Questi due post sono stati di grande aiuto:
Questo mostra come ricavare il codice dell'etichetta cercando in base al testo:
https://community.dynamics.com/365/financeandoperations/f/dynamics-365-for-finance-and-operations-forum/272482/how-to-get-label-id-from-a-label-text/810927
Questo post invece indica come ricavare tutti i fileID delle etichette:
https://community.dynamics.com/365/financeandoperations/f/dynamics-365-for-finance-and-operations-forum/243050/enumerate-label-prefix-for-label-search-functionality
Questo è il job preso dal primo link e modificato:
Lanciando il job otterremo il seguente risultato:
Questi due post sono stati di grande aiuto:
Questo mostra come ricavare il codice dell'etichetta cercando in base al testo:
https://community.dynamics.com/365/financeandoperations/f/dynamics-365-for-finance-and-operations-forum/272482/how-to-get-label-id-from-a-label-text/810927
Questo post invece indica come ricavare tutti i fileID delle etichette:
https://community.dynamics.com/365/financeandoperations/f/dynamics-365-for-finance-and-operations-forum/243050/enumerate-label-prefix-for-label-search-functionality
Questo è il job preso dal primo link e modificato:
public static void main(Args _args)
{
int j;
//parametri - start
str TextToFind = "Data fattura"; //stringa da cercare
LanguageId languageId = "it"; //lingua
boolean matchExactly = true; //trova parola esatta oppure no
str LabelFile = "SYS"; //Label file Id
//parametri - end
container result;
Map txtToLabelIdMap = new Map(Types::String, Types::String);
ClrObject labels = new ClrObject("System.Collections.Generic.Dictionary`2[System.String,System.String]");
System.Globalization.CultureInfo cultInfo = System.Globalization.CultureInfo::CreateSpecificCulture(languageId);
labels = Microsoft.Dynamics.Ax.Xpp.LabelHelper::GetAllLabels(LabelFile, cultInfo);
if(labels)
{
ClrObject labelsEnumerator = labels.GetEnumerator();
while(labelsEnumerator.MoveNext())
{
ClrObject keyValuePair = labelsEnumerator.get_Current();
var currentlabelId = keyValuePair.get_Key();
var currentTxt = keyValuePair.get_Value();
if(matchExactly)
{
if(currentTxt == TextToFind)
{
if (!Microsoft.Dynamics.Ax.Xpp.LabelHelper::IsLegacyLabelId(currentlabelId))
{
currentlabelId = strFmt("%1%2:%3","@",LabelFile,currentlabelId);
}
result += strFmt("%1,%2 -> %3",LabelFile,currentlabelId,currentTxt);
}
}
else
{
if(strScan(currentTxt, TextToFind, 0, strLen(currentTxt)))
{
if (!Microsoft.Dynamics.Ax.Xpp.LabelHelper::IsLegacyLabelId(currentlabelId))
{
currentlabelId = strFmt("%1%2:%3","@",LabelFile,currentlabelId);
}
result += strFmt("%1,%2 -> %3",LabelFile,currentlabelId,currentTxt);
}
}
}
}
//container dei risultati
for(j = 1;j<=conLen(result);j++)
{
info(conPeek(result,j));
}
}
Lanciando il job otterremo il seguente risultato:
mercoledì 12 febbraio 2020
Notepad ++ Plug in x++
In questo post segnalo un utile plug in per l'editor Notepad++ per aggiungere tra i linguaggi l'x++.
Il plug è scaricabile da quì:
https://jrabascal.wordpress.com/2014/07/07/creating-user-defined-language-x-into-the-notepad/
Nel link trovate le instruzioni per l'installazione
Ho apportato qualche piccola modifica alle colorazioni delle parole chiavi, l'evidenziazione delle etichette e dei blocchi.
Potete scaricare il file da quì:
https://mega.nz/#!WE9lRY7S!6A-3Wf_vDcEFdFehS5Tikh3pf5cHUzDQfgaPbml0B4w
Questo un esempio:
Il plug è scaricabile da quì:
https://jrabascal.wordpress.com/2014/07/07/creating-user-defined-language-x-into-the-notepad/
Nel link trovate le instruzioni per l'installazione
Ho apportato qualche piccola modifica alle colorazioni delle parole chiavi, l'evidenziazione delle etichette e dei blocchi.
Potete scaricare il file da quì:
https://mega.nz/#!WE9lRY7S!6A-3Wf_vDcEFdFehS5Tikh3pf5cHUzDQfgaPbml0B4w
Questo un esempio:
giovedì 16 gennaio 2020
AX 2012 - SSRS - Errore su report parameter ‘AX_CompanyName’
Mi è capitato varie volte di imbattermi nel seguente errore quando vado a stampare il primo report dopo il riavvio dei servizi di reporting. L'errore scompare dalla seconda stampa.
"The DefaultValue expression for the report parameter ‘AX_CompanyName’ contains an error: Request for the permission of type 'System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed. (rsRuntimeErrorInExpression)"
L'errore non risulta quindi bloccante ma è piuttosto fastidioso, soprattuto quando capita ad un utente. Quello che posso suggerirvi è di modificare come segue il file rssrvpolicy.config all'interno delle cartelle di SSRS, impostando l'autorizzazione "FullTrust" al posto di "Esegui" per "Report_Expressions_Default_Permissions".
Configurazione iniziale:
<CodeGroup
class="UnionCodeGroup"
version="1"
PermissionSetName="Execution"
Name="Report_Expressions_Default_Permissions"
Description="This code group grants default permissions for code in report expressions and Code element. ">
class="UnionCodeGroup"
version="1"
PermissionSetName="Execution"
Name="Report_Expressions_Default_Permissions"
Description="This code group grants default permissions for code in report expressions and Code element. ">
[...]
</CodeGroup>
Configurazione modificata:
<CodeGroup
class="UnionCodeGroup"
version="1"
PermissionSetName="FullTrust"
Name="Report_Expressions_Default_Permissions"
Description="This code group grants default permissions for code in report expressions and Code element. ">
[..]
</CodeGroup>
Fonte:
https://community.dynamics.com/ax/b/axsupport/archive/2012/02/02/microsoft-dynamics-ax-2012-reporting-extensions-error-system-security-permissions-environmentpermission-while-running-report
AX 2012 - Job Fieldname print
In this post I'll share a job made in order to print an infolog having all the fields of a table in ax with some useful information like, field name, label, help text, data type.
Con questo job invece possiamo stampare il contenuto di una tabella (lista dei campi e valore) in maniera dinamica: static void AGIA_TableFieldNames_2(Args _args)
{
DictTable dt = new SysDictTable(77);
FieldId _fieldId = dt.fieldNext(0);
DictField _dictField;
Dialog dialog;
DialogField myDialogField;
tablename id;
dialog = new dialog();
myDialogField = dialog.addField(extendedTypeStr(tablename), "TableName : ");
dialog.run();
if(dialog.closedOk())
{
id = myDialogField.value();
dt = new sysdicttable(tableName2id(id));
info(strFmt("Field Name; Field Label; Field Type; Field Help; Field Mandatory; Field Lenght"));
if(_fieldId)
while(_fieldId)
{
_dictField =dt.fieldObject(_fieldId);
if(_dictField)
{
if(!_dictField.isSystem())
{
info(strFmt("%1; %2; %3; %4; %5; %6", _dictField.name(),_dictField.label(),_dictField.baseType(),_dictField.help(),_dictField.mandatory(), _dictField.stringLen()));
_fieldId= dt.fieldNext(_fieldId);
}
}
}
else
{
info(strFmt("Missing table %1", id));
}
}
}
static void LIL_PrintTableValue(Args _args)
{
DictTable dt;
DictField dictField;
Common common;
Counter i=0;
FieldId fieldId;
dt = new DictTable(tableNum(InventSite));
common = dt.makeRecord();
while select common
{
fieldId = dt.fieldNext(0);
while (fieldId)
{
dictField = dt.fieldObject(fieldId);
if(dictField.configurationKeyId() != configurationkeynum(SysDeletedObjects60))
{
info(strFmt("%1 = %2",fieldId2name(dt.id(),dictField.id()),common.(dictField.id())));
}
fieldId = dt.fieldNext(fieldId);
}
info("---------------------");
}
}
mercoledì 26 giugno 2019
AX 2012 - Job per creazione progetto da CSV
In questo post pubblico un job che ho scritto che serve per creare un progetto privato leggendo un csv contenente una lista di tipi e nomi degli elementi dell'AOT
L'output sarà il seguente:
static void LIL_ProjectElementAdd(Args _args)
{
TextIo inFile;
container line;
Counter records;
SysOperationProgress simpleProgress;
container fileContainer;
Counter loopCounter;
CustTable CustTable;
InventTable InventTable;
str filename,
properties,
objectType,
objectName,
aotType,aotPath;
TreeNode projectNode,
tempNode;
ProjectGroupNode groupNode;
boolean managed;
#OCCRetryCount
#AviFiles
#File
#aot
#DMF
filename = WinAPI::getOpenFileName(0,
[WinAPI::fileType(#csv),#AllFilesName + #csv],
strFmt(@'C:\users\%1\Desktop',WinApi::getUserName()),
"@SYS53008"
);
try
{
inFile = new TextIo(filename, 'r');
inFile.inRecordDelimiter('\n');
inFile.inFieldDelimiter(';');
while (inFile.status() == IO_Status::OK)
{
fileContainer += [infile.read()];
}
inFile = null;
}
catch
{
throw error(strFmt("@SYS18678", filename));
}
simpleProgress = SysOperationProgress::newGeneral(#aviUpdate, "Importazione...", conLen(fileContainer));
records = 0;
projectNode = SysTreeNode::createProject("MyPrivateProject");
groupNode = projectNode.AOTadd("Object");
properties = groupNode.AOTgetProperties();
for (loopCounter = 2; loopCounter <= conLen(fileContainer) - 1 ; loopCounter++)
{
line = conPeek(fileContainer,loopCounter);
objectType = conPeek(line,1);
objectName = conPeek(line,2);
switch(objectType)
{
case "BaseEnum" :
aotType = #BaseEnums;
aotPath = #BaseEnumsPath;
managed = true;
break;
case "Class" :
aotType = #Classes;
aotPath = #ClassesPath;
managed = true;
break;
case "ExtendedDataType" :
aotType = #ExtendedDataTypes;
aotPath = #ExtendedDataTypesPath;
managed = true;
break;
case "Form" :
aotType = "Forms";
aotPath = #FormsPath;
managed = true;
break;
case "Macro" :
aotType = "Macros";
aotPath = #MacrosPath;
managed = true;
break;
case "Menu" :
aotType = "Menus";
aotPath = #MenusPath;
managed = true;
break;
case "Table" :
aotType = "Tables";
aotPath = #TablesPath;
managed = true;
break;
case "Map" :
aotType = "Maps";
aotPath = #TableMapsPath;
managed = true;
break;
case "Query" :
aotType = #Queries;
aotPath = #QueriesPath;
managed = true;
break;
case "SecurityDuty" :
aotType = "SecDuties";
aotPath = #SecDutiesPath;
managed = true;
break;
case "SecurityPrivilege" :
aotType = "SecPrivileges";
aotPath = #SecPrivilegesPath;
managed = true;
break;
case "SecurityPrivilege" :
aotType = "SecPrivileges";
aotPath = #SecPrivilegesPath;
managed = true;
break;
case "SecurityProcessCycle" :
aotType = "SecProcessCycles";
aotPath = #SecProcessCyclesPath;
managed = true;
break;
case "SecurityRole" :
aotType = "SecRoles";
aotPath = #SecRolesPath;
managed = true;
break;
case "SSRSReport" :
aotType = "SSRSReports";
aotPath = #SSRSReportsPath;
managed = true;
break;
case "VisualStudioProjectCSharp" :
aotType = "VSProjectsCShar";
aotPath = #VSProjectsCSharpPath;
managed = true;
break;
default:
managed = false;
warning(strFmt("Unable to add %1, %2",objectType,objectName));
}
if(objectName && managed)
{
tempNode = TreeNode::findNode(aotPath);
groupNode.addNode(tempNode.AOTfindChild(objectName));
}
}
projectNode.AOTsave();
}
L'output sarà il seguente:
Iscriviti a:
Post (Atom)


