Options

Upload files without prompting for filename

sbssbs Member Posts: 27
edited 2013-12-04 in NAV Three Tier
Hi

For this pojeckt am I using NAV 2009 SP1.

I want to upload all files in a folder into nav. In classic this works fine but now I want to use rtc...
I can get rtc to upload a file but I always have to choose my file first. (I don't want to do that)
Is there a way to upload every file in the folder without asking anything of the user?

like this in classic

InFile.SETRANGE(Path, SalesSetup."My File Folder" + '\');
InFile.SETRANGE("Is a file", TRUE);
IF InFile.FINDSET THEN BEGIN

// here some code for taking care of the textfile...

REPEAT UNTIL InFile.NEXT=0;

Answers

  • Options
    ppavukppavuk Member Posts: 334
    I think there is no way to use file virtual table on client, as code is execute on middle-tier. You can use windows scripting host automation (instantiated on client) to list folder contents.
  • Options
    sbssbs Member Posts: 27
    Thank You,
    do you happen to have an example or link to look at how to use this automation?
  • Options
    ppavukppavuk Member Posts: 334
    read this one: http://www.mibuso.com/forum/viewtopic.php?t=7855

    Look for azwierzchowski reply.
  • Options
    sbssbs Member Posts: 27
    That solution works fine... in classic.
    There was also a solution for RTC if you have 2009 R2, unfortunately we are using 2009 sp1 :(
  • Options
    ppavukppavuk Member Posts: 334
    This should work ok for rtc, just define windows scripting host variables to be run on client.
  • Options
    sbssbs Member Posts: 27
    How do i define windows scripting host variables to be run on client? :?:

    The program stops on the line
    LautFolder := LautFileSystemObject.GetFolder(MyFolder);
  • Options
    sbssbs Member Posts: 27
    All above have helped me a bit on my way, but ...

    If I try to run it in RTC I got the following error: Could not compile assembly...

    I have commented out code and it run fine if I comment out these two lines
    WHSFile := FilesCol.Item(i);
    ltxtFileName := WHSFolder.Path + '\' + WHSFile.Name;

    Any ideas?


    Here is my code:

    IF ISCLEAR(WHSFileSystemObject) THEN
    CREATE(WHSFileSystemObject,TRUE,TRUE);

    // If the folder does not exist, exit
    IF NOT WHSFileSystemObject.FolderExists(MyFolder) THEN BEGIN
    CLEAR(WHSFileSystemObject);
    EXIT;
    END;

    WHSFolder := WHSFileSystemObject.GetFolder(MyFolder);
    WHSFiles := WHSFolder.Files;

    IF ISCLEAR(FilesCol) THEN
    CREATE(FilesCol,TRUE,TRUE);

    // ========================================================================
    // Use a VBScript to fill a 'Microsoft Scripting Runtime'.Dictionary
    IF ISCLEAR(Script) THEN
    CREATE(Script,TRUE,TRUE);

    Script.Language := 'VBScript';
    //variable LautFolders is visible in script as FoldersByName
    Script.AddObject('FilesByName', WHSFiles);
    //variable FoldersCol is visible in script as FoldersById
    Script.AddObject('FilesById', FilesCol);

    //copy objects using VBScript
    txtCR := '';
    txtCR[1] := 13;
    txtcode :=
    'dim f1' + txtCR +
    'For Each f1 in FilesByName' + txtCR +
    ' FilesById.Add (FilesById.Count+1), f1' + txtCR +
    'Next' + txtCR;
    Script.ExecuteStatement(txtcode);
    CLEAR(Script);
    // ========================================================================

    FileCount := FilesCol.Count();
    FOR FileInt := 1 TO FileCount DO BEGIN
    WHSFile := FilesCol.Item(i); <---- Here is the problem!
    ltxtFileName := WHSFolder.Path + '\' + WHSFile.Name;
    // ==========================
    // Here you do what you want to do with the file...
    // MESSAGE(ltxtFileName);
    // ==========================
    END;

    CLEAR(FilesCol);
    CLEAR(WHSFileSystemObject);
  • Options
    ppavukppavuk Member Posts: 334
    sbs wrote:
    All above have helped me a bit on my way, but ...

    If I try to run it in RTC I got the following error: Could not compile assembly...

    Can you please post c# assembly? I think c/al -> c# translator messing up with your code. Would be interesting to see how this looks in c#.
  • Options
    sbssbs Member Posts: 27
    Hi

    I don't know how to do that :oops:
  • Options
    ppavukppavuk Member Posts: 334
    set your server to debug mode (google howto edit config)
    after first client run somewhere under "C:\ProgramData\Microsoft\Microsoft Dynamics NAV\60\Server\MicrosoftDynamicsNavServer\source\" on server machine you will find c# files for each object.
  • Options
    sbssbs Member Posts: 27
    Here is the C# assembly:

    sing System;
    using Microsoft.Dynamics.Nav.Runtime;
    using Microsoft.Dynamics.Nav.Types;
    using Microsoft.Dynamics.Nav.Types.Exceptions;
    using Microsoft.Dynamics.Nav.Common.Language;

    namespace Microsoft.Dynamics.Nav.BusinessApplication
    {
    //Travel Management
    public sealed class Codeunit50000 : NavCodeunit
    {
    #region Non-user code (Declarations, constructors, properties)
    #line hidden
    private NavRecordHandle salesSetup;
    private NavRecordHandle inFile1;
    private NavFile inFile = null;
    private NavText line = NavText.Default(500);
    private NavArray<NavText> lineField;
    private NavCode lineID = NavCode.Default(10);
    private Int32 nextnr = 0;
    private Int32 nextLineno = 0;
    private Int32 delimeterplace = 0;
    private Int32 fileLen = 0;
    private NavXmlPortHandle importXMLPort;

    public Codeunit50000(ITreeObject parent) : base(parent, 50000)
    {
    InitializeComponent();
    }
    private NavFile PInFile
    {
    get
    {
    if(inFile==null)
    {
    inFile = new NavFile(this);
    }

    return (inFile);
    }
    set
    {
    inFile = value;
    }

    }

    #line default
    #endregion Non-user code (Declarations, constructors, properties)
    #region Non-user code
    #line hidden

    private void InitializeComponent()
    {

    salesSetup = new NavRecordHandle(this, 311);
    inFile1 = new NavRecordHandle(this, 2000000022);

    }

    protected override Object OnInvoke(Int32 memberId,Object[] args)
    {
    using (NavMethodScope __local = new NavMethodScope(this, @OnInvoke))
    {
    switch(memberId)
    {
    case 1000000000:
    {

    {
    if(args.Length!=0)
    {
    NavRuntimeHelpers.CompilationError(new NavNCLInvalidNumberOfArgumentsException(@ImportFile, 0, args.Length));
    }

    ImportFile();
    }

    }
    break;
    default:
    {
    NavRuntimeHelpers.CompilationError(Lang.WrongReference, memberId, 50000);
    }
    break;

    }

    return (null);
    }

    }

    protected override void OnClear()
    {
    this.salesSetup.Clear();
    this.inFile1.Clear();
    ALSystemVariable.Clear(this.inFile);

    }

    #line default
    #endregion Non-user code

    public void ImportFile()
    {
    using (NavMethodScope __local = new NavMethodScope(this, @ImportFile))
    {

    NavText tmpstr = NavText.Default(150);
    NavText filename = NavText.Default(150);
    NavText filename2 = NavText.Default(150);
    NavAutomation script = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}, @&quot;", null);
    NavText txtcode = NavText.Default(1024);
    NavVariant retVal = NavVariant.Default(__local);
    Int32 count = 0;
    Int32 i = 0;
    NavText txtCR = NavText.Default(30);
    NavText foldername = NavText.Default(1024);
    NavAutomation wHSFileSystemObject = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{0D43FE01-F093-11CF-8940-00A0C9054228}, null, null);
    NavAutomation wHSFolder = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{C7C3F5B3-88A3-11D0-ABCB-00A0C90FFFC0}, null, null);
    NavAutomation wHSFiles = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{C7C3F5B6-88A3-11D0-ABCB-00A0C90FFFC0}, null, null);
    NavAutomation wHSFilesCollection = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{387DAFF4-DA03-44D2-B0D1-80C927C905AC}, null, null);
    NavAutomation wHSFile = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{C7C3F5B5-88A3-11D0-ABCB-00A0C90FFFC0}, null, null);
    Int32 fileCount = 0;
    Int32 fileInt = 0;
    NavAutomation filesCol = new NavAutomation(__local, NavAutomation.ComponentType.Automation, @{EE09B103-97E0-11CF-978F-00A02463E06F}, null, null);
    NavText selectedFolder = NavText.Default(1024);
    NavText serverFilePath = NavText.Default(1024);
    NavText clientTempFile = NavText.Default(1024);
    Boolean status = new Boolean();


    // IF ISCLEAR(WHSFileSystemObject) THEN
    if(wHSFileSystemObject.IsClear)
    {
    // CREATE(WHSFileSystemObject,TRUE,TRUE);
    wHSFileSystemObject.Create(DataError.ThrowError, true, true);
    }

    // IF NOT WHSFileSystemObject.FolderExists('P:\') THEN BEGIN
    if(!(wHSFileSystemObject.InvokeMethod<Boolean>(@FolderExists, @P:\)))
    {

    ALSystemVariable.Clear(wHSFileSystemObject);
    // EXIT;
    return ;
    }

    // WHSFolder := WHSFileSystemObject.GetFolder('P:\');
    wHSFolder.ALAssign(wHSFileSystemObject.InvokeMethod<NavAutomation>(@GetFolder, @P:\));
    // WHSFiles := WHSFolder.Files;
    wHSFiles.ALAssign(wHSFolder.InvokePropertyGet<NavAutomation>(@Files));
    // IF ISCLEAR(FilesCol) THEN
    if(filesCol.IsClear)
    {
    // CREATE(FilesCol,TRUE,TRUE);
    filesCol.Create(DataError.ThrowError, true, true);
    }

    // IF ISCLEAR(Script) THEN
    if(script.IsClear)
    {
    // CREATE(Script,TRUE,TRUE);
    script.Create(DataError.ThrowError, true, true);
    }

    // Script.Language := 'VBScript';
    script.InvokePropertySet<String>(@Language, @VBScript);
    // Script.AddObject('FilesByName', WHSFiles);
    script.InvokeMethod<Object>(@AddObject, @FilesByName, wHSFiles);
    // Script.AddObject('FilesById', FilesCol);
    script.InvokeMethod<Object>(@AddObject, @FilesById, filesCol);
    // txtCR := '';
    txtCR = new NavText(30, @&quot;");
    txtCR = new NavText(30, ALSystemString.SetChar(txtCR, 0, ALCompiler.ToByte(13)));
    // txtcode :=
    txtcode = new NavText(1024, @dim f1+txtCR+@For Each f1 in FilesByName+txtCR+@ FilesById.Add (FilesById.Count+1), f1+txtCR+@Next+txtCR);
    // Script.ExecuteStatement(txtcode);
    script.InvokeMethod<Object>(@ExecuteStatement, txtcode);
    // // ========================================================================
    ALSystemVariable.Clear(script);
    // FileCount := FilesCol.Count();
    fileCount = filesCol.InvokePropertyGet<Int32>(@Count);
    // MESSAGE(FORMAT(FileCount));
    NavDialog.ALMessage(new Guid(50000, 15259, 51712, 3, 5, 0, 0, 131, 107, 210, 210), NavFormatEvaluateHelper.Format(ALCompiler.ToNavValue(fileCount)));
    fileInt = 1;
    Int32 @tmp0 = fileCount;
    // FOR FileInt := 1 TO FileCount DO BEGIN
    for(;fileInt<=@tmp0;)
    {
    // WHSFile := FilesCol.Item(i);
    wHSFile.ALAssign(filesCol.InvokePropertySet<Object>(@Item, ( (Object)(i) )));
    // filename := WHSFolder.Path + '\' + WHSFile.Name;
    filename = new NavText(150, wHSFolder.InvokePropertyGet<String>(@Path)+@\+wHSFile.InvokePropertyGet<String>(@Name));
    if(fileInt>=@tmp0)
    {
    break;
    }

    fileInt = fileInt+1;
    }

    // CLEAR(WHSFileSystemObject);
    ALSystemVariable.Clear(filesCol);
    //
    ALSystemVariable.Clear(wHSFileSystemObject);
    }

    }

    }

    }
  • Options
    ppavukppavuk Member Posts: 334
    for me this line isn't looks good:

    filename = new NavText(150, wHSFolder.InvokePropertyGet<String>(@Path)+@\+wHSFile.InvokePropertyGet<String>(@Name));

    I am not a c# expert, but what happens if you just hardcode path in c/al, something like
    filename := 'c:\temp\test.txt'
    

    Looks that c/al -> c# translator can't convert your expression into valid c# code.
  • Options
    sbssbs Member Posts: 27
    thanx

    but it fails even if i comment away that line, it is the line before that that is the problem.

    And i can't hardcode it to something - the whole idea is to get those filenames :-)

    I have now tried the same code in 2009 R2 and i get the same errortext
  • Options
    deV.chdeV.ch Member Posts: 543
    What do you try to achieve with the VBScript part? Do you need the files in a specific order?
  • Options
    ppavukppavuk Member Posts: 334
    The thing is - you need to find out line which can't be compiled in c# and change it to make it compilable.
  • Options
    deV.chdeV.ch Member Posts: 543
    The OP said which line produces the error:
    FileCount := FilesCol.Count();
    FOR FileInt := 1 TO FileCount DO BEGIN
    WHSFile := FilesCol.Item(i); <---- Here is the problem!
    ltxtFileName := WHSFolder.Path + '\' + WHSFile.Name;

    I would like to know why you even need the whole VBScript part? Why not looping over the WSHFiles Collection?
  • Options
    sbssbs Member Posts: 27
    I would like to know why you even need the whole VBScript part? Why not looping over the WSHFiles Collection?

    yes, I tried to do that
    WHSFile := WHSFiles.Item(i);

    But then it complains over my parameters.
    the WHSFiles are sorted by names - and I don't know the filenames

    all files are there
    FileCount := WHSFiles.Count(); works fine
    I just don't can't get the names from them :roll:
  • Options
    deV.chdeV.ch Member Posts: 543
    Please have a look at this, especially page 2 (if you don't have already) http://www.mibuso.com/forum/viewtopic.php?f=5&t=7855&start=15

    If you can, i would recommend using .Net interop instead. There you don't have such limitations. The collections work as expected in the System.IO Namespace you will find all you need (Directory Class which returns file names as string)

    Or if you must stick to automations, try the "Microsoft Shell Controls And Automation'.Shell" instead.
    MSShell	Automation	'Microsoft Shell Controls And Automation'.Shell	
    MSFolder	Automation	'Microsoft Shell Controls And Automation'.Folder	
    MSFolderItem	Automation	'Microsoft Shell Controls And Automation'.FolderItem	
    
    Create(MSShell, TRUE, TRUE);
    
    MSFolder := MSShell.NameSpace('C:\Temp\');
    For i := 1 TO MSFolder.Items.Count DO BEGIN
      MSFolderItem := MSFolder.Items.Item(i);
      Message(MSFolderItem.Path);
    END;
    
  • Options
    sbssbs Member Posts: 27
    Thanx,

    In the thread it says that .NET only works with R2, I am using 2009 sp1.
    But I will try "Microsoft Shell Controls And Automation'.Shell"
    What do you try to achieve with the VBScript part? Do you need the files in a specific order?
    No specific order. I just want the name of all the files in a specific folder.
  • Options
    sbssbs Member Posts: 27
    =D>

    The MSFolder version works!

    Thank You all for your suggestions and links

    Here is my final code (anyway "final" before put into real context)
  • Options
    casanovacasanova Member Posts: 194
    how to filter i just want to read "txt" file?
    thx
Sign In or Register to comment.