How to access file resource via LotusScript - lotus-notes

I want to access and use shared file. I considered these approaches:
1. Store the attachment in Notes Document
2. Store the attachment in database profile
but in both cases I will need to add extra UI design elements (form, view... )
So the easiest way to maintain it - use db Resources (images or files).
I need to create LotusSrcit action that would access the file from db Resources and attach it into new NotesDocument that will be sent as an email.
1 and #2 easy to implement. But how can I access certain file resource from db Resources?

You can access file or image resources using the NotesNoteCollection class. However, since Notes stores the attached files or images in its own, internal format, it is not easy -- if at all possible -- to access those attachments using pure LotusScript.
A workaround that I found useful is to attach the file to an Applet resource, where it can be accessed using pure LotusScript; see sample code below.
Dim sn As New NotesSession()
Dim db as NotesDatabase
Dim nc As NotesNoteCollection
Dim designNote As NotesDocument
Dim eo As NotesEmbeddedObject
Dim noteID$, myFileName$
myFileName = "foobar.txt"
Set db = sn.CurrentDatabase
Set nc = db.CreateNoteCollection(False)
nc.SelectJavaResources = True 'select all Applet resources
nc.SelectionFormula = {$TITLE="} + myFileName + {"} 'assuming the Applet resource has the same name as the file
Call nc.BuildCollection()
noteID = nc.GetFirstNoteID()
Do Until Len(noteID) = 0
Set designNote = db.GetDocumentByID(noteID)
Set eo = designNote.GetAttachment(myFileName)
If Not (eo Is Nothing) Then
'----- your code goes here -----
Exit Do
End If
noteID = nc.GetNextNoteID(noteID)
Loop
I'm making two assumptions here:
The name of the file you want to access is known ("foobar.txt" in the sample code). This is necessary, since otherwise you won't be able to access the attachment.
The Applet resource has the same name as the attached file. Not necessary, but convenient for being able to filter the NotesNoteCollection by the very name of the attached file.

Related

Bypass transaction for logging

I'm importing data from Excel to Access. During the import I validate it and I insert only rows that are ok. Errors are logged into another table that is later used by a report. The import is done manually with a VBA macro. I use CurentDb.OpenRecordset for writing.
Current solution: only valid data + keep logs
I import data from Excel row by row and keep them in the database after the import. Even if I find errors in other rows.
At the same time I log errors into another table.
Desired solution: all or nothing + keep logs
Commit the imported data only if all data is valid.
Keep the error log also when the imported data is rolled back to show a report.
Issue
When I rollback the imported data, the logs are also rolledback so I cannot use it for reporting.
Question
Is there a way to bypass the import transaction so that the log is always written?
You can create multiple workspaces and corresponding database objects, which have separate transactions, even on the database that's currently open. Note that this won't work if you have an exclusive lock on the database.
Dim wsLog As DAO.Workspace
Dim wsImport As DAO.Workspace
Dim dbImport As DAO.Database
Dim dbLog As DAO.Database
Dim dbe As DAO.DBEngine
Set dbe = DBEngine
Set wsLog = dbe.CreateWorkspace("wsLog", "Admin", "")
Set wsImport = dbe.CreateWorkspace("wsImport", "Admin", "")
Set dbLog = wsLog.OpenDatabase(CurrentProject.FullName)
Set dbImport = wsImport.OpenDatabase(CurrentProject.FullName)
wsImport.BeginTrans
dbImport.Execute "INSERT INTO Table1(Field1) VALUES(1)" 'Do your imports/processing in this workspace
wsLog.BeginTrans
dbLog.Execute "INSERT INTO Table2(Field1) VALUES(1)" 'And logging here
wsLog.CommitTrans 'Commit log
wsImport.Rollback 'Rollback import afterwards
'Result: Table2 is changed, Table1 isn't
Note that while it's not required to use a separate logging database, if you use Access for storage, I do recommend it.
And, as said in the comments, you can just work with a temporary table too.
You create a permanently invisible table that's intended for temporary use using CreateTableDef with the dbHiddenObject constant:
CreateTableDef("TableName", dbHiddenObject)
It won't get removed automatically, so it's not temporary in that sense, though. And keep in mind that deleting + recreating temporary tables will increase the database size, likely requiring more compact operations.

Notes EMBEDDEDOBJECT (1090) doesn't return an inline image

The following article Notes items gives the description of all Notes items. It is mentioned that EMBEDDEDOBJECT (1090) means embedded object. Yet, my code doesn't work for this part.
Following is the piece of code to extract the image:
If edoc.HasEmbedded Then
ForAll x In edoc.items
If x.Type = 1090 Then
Set neoAttachment = edoc.GetAttachment(x.values(0))
strImageFilepath = Temppath & neoAttachment.name
Call neoAttachment.ExtractFile(strImageFilepath)
Set Attachobject = rititem.EmbedObject( EMBED_ATTACHMENT, "", strImageFilepath)
End If
End Forall
If I specify as x.Type=1090, then the inliine image doesn't get extracted.
But if I specify as x.Type=1084(which means file attachment), in the same piece of code, it works.
Inline image is supposed to be an embedded object and not an attachment. Could anyone please tell the reason for this issue?
The Notes architecture has evolved over time, and the vocabulary is a bit... Ummmm... difficult.
An embedded object can be either an attachment or an OLE object. There are (normally) two parts to an embedded object: a piece of data that marks the place where the object appears in NotesRichTextItem, and a separate piece of data that stores the actual bits for the object. In both cases, the marker is accessed through the NoteRichTextItem and is referred to as an embedded object, but the actual bits are stored in their own separate NotesItem, outside of the NotesRichTextItem. The NotesEmbeddedObject class works with both parts, and tries to hide the existence of the second item from you, but it's always there.
Type 1090 would be an embedded OLE object. In the case of an embedded object that is an inline image, the NotesItem object is stored as a file attachment, type 1084.

Access Shared Network Folder

I need to access via VBA a folder hosted on a Network File Server. The folder is accessible in writing only via a Service Account (different from normal user accounts) for which I do have username and password.
Via the UI I can see that folder and map it as a local drive but in order to access it in writing I need to log off from Windows and logon via the Service Account.
Is there any way to access the network folder during a normal user session but hardcoding username and pwd in the VBA code?
I did try mapping the folder as local drive with:
Set WshNetwork = CreateObject("WScript.Network")
WshNetwork.MapNetworkDrive "S:", "\\corp-server\HostingFolder", False, Username, pwd
but did not work ("S" drive was not mapped). If instead I do the same but without providing Username and password:
Set WshNetwork = CreateObject("WScript.Network")
WshNetwork.MapNetworkDrive "S:", "\\corp-server\HostingFolder"
it works perfectly.
Wondering now if what I am trying to do is actually possible? If not, is there any alternative?
Thanks
You might find this answer of value in your testing.
Essentially, I would check a couple things...
Make sure you are not already connected to this resource using the current logged in user. If you are, you might get an error message like the following:
Make sure you are using the domain\username syntax in your username.
Otherwise I think you are the right track. I put together some sample code based on the link above, and was able to successfully connect to a network share under a different user name and iterate through a list of files.
(Note the tip that you don't actually have to map a drive to establish a connection.)
The following code is a really quick (working) VBA implementation of the sample listed at Access network share from within VBScript eg FileSystemObject
Public Sub TestNetShareName()
Dim NetworkObject As Object
Dim FSO As Object
Dim Directory As Object
Dim Filename As Object
Dim ServerShare As String
Dim UserName As String
Dim Password As String
ServerShare = "\\corp-server\HostingFolder"
UserName = "mydomain\myuser"
Password = "freddie123"
Set NetworkObject = CreateObject("WScript.Network")
Set FSO = CreateObject("Scripting.FileSystemObject")
NetworkObject.MapNetworkDrive "", ServerShare, False, UserName, Password
Set Directory = FSO.GetFolder(ServerShare)
For Each Filename In Directory.Files
Debug.Print Filename.Name
Next
Set Filename = Nothing
Set Directory = Nothing
Set FSO = Nothing
NetworkObject.RemoveNetworkDrive ServerShare, True, False
Set NetworkObject = Nothing
End Sub

LotusScript:Agents on schedule does not run DbLookup

I'm writing a LotusScript agent that runs on schedule. In the script, there is a line that
goes something like
Dim eval as Variant
eval = Evaluate({#DbLookup( "": ""; "SVR1": "db.nsf"; "aView"; "KeyValue"; 4})
Where SVR1 is the servername, db.nsf is the database, aView is the view and KeyValue is the key used to access the desired record(s). The last number 4 is the column number of the view that we want the value from.
I've been doing this for awhile and no problems. Only now does the script seem not to run on schedule. It works if i run it manually via the designer. I've used NotesLog to do debug and i noticed the agents stops right at that line. The db it is looking up is on another server.
What is causing this script to fail?
Seems that you are trying to connect to the server, different than the agent is running on.
In the old lotus versions there was a strict rule, you was not able to connect to another server in the scheduled agent.
I.e if you ran your scheduled agent on the server: SRV0 you was able only to get information from the server SRV0.
Later (if I recall correctly in Domino 6.0 and later) the new term included: trusted server.
So, if you want to access another server from your scheduled agents you need to register this server as a trusted server.
To add server to trusted servers list, open your server document in the server address book.
Go to Security tab and specify trusted servers in the corresponding field.
I recommend to not use the Evaluate in a such way. Instead of this is better to use native LotusScript objects like NotesDatabase, NotesView and so on:
Dim db As New NotesDatabase("", "")
Dim view As NotesView
Dim vc As NotesViewEntryCollection
Dim entry As NotesViewEntry
Dim eval as Variant
Call db.Open("SRV1/OrgUnit/Organization", "db.nsf")
Set view = db.GetView("aView")
Set vc = view.GetAllEntriesByKey("KeyValue", True)
If vc.Count = 0 Then
Exit Sub
End If
Redim eval(vc.Count - 1)
Set entry = vc.GetFirstEntry
index% = -1
Do While Not entry is Nothing
index% = index% + 1
eval(index%) = entry.ColumnValues(3)
Set entry = vc.GetNextEntry(entry)
Loop

How do I remove IIS based components from InstallShield in an upgrade?

In trying to create a major upgrade existing web applications with InstallShield as suggested here I have created a new application pool, but can't create a new IIS application. However while the new install creates the new pool, it doesn't change the existing virtual directory to use the new pool. The logs say virtual directory already exists and leaves it at that.
Is it possible to get the install to change an existing component, or simply how do I delete the virtual directory component since the remove files table expects a directory?
Thanks
Ended up achieving this by
Created a Property called WEBSITENAME with the value of the website name from the String Editor table (this is for reuse)
Created a VBscript custom action, to run after RemoveFolders with the following condition: IIS_VERSION <= "#6" and NOT INSTALLED
The code is:
Dim objWebServer
Dim objVirtualDir
Dim strAppName
Dim intASPSessionTimeout
Dim SubVirtDir
On Error Resume Next
CreateApplication = ERROR_SUCCESS
strAppName = Session.Property("WEBSITENAME")
SubVirtDir = "/" + strAppName
intASPSessionTimeout = 120
Set objWebServer = GetObject("IIS://localhost/W3SVC/1/Root")
'Delete the Virtual subdirectory
Set objVirtualDir = objWebServer.Delete("IISWebVirtualDir", SubVirtDir)
Set objVirtualDir = objWebServer.Delete("IISWebVirtualDir", strAppName)
This does what I needed to do. Now I need to figure out a similar way to conditionally Enable32bitAppOnWin64!

Resources