I'm writing a code to export the CSV using free file in lotus notes the code works fine but I'm facing an issue while closing the file explorer window. The scenario is if I don't need to export now and unknownly click export button it asks for fine name opening the file explorer window. The file explorer window it is not closing it asks for filename and its looping till i give the file name.
My code:
Sub Initialize
Dim ws As New NotesUIWorkspace
Dim session As New NotesSession
Dim source As NotesUIDocument
Dim db As NotesDatabase
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Dim headerString As String
Dim header As Variant
Dim sno As Variant
Dim vw As NotesView
Dim flag As Boolean
REM Get selected document
Set db = session.CurrentDatabase
Set dc = db.UnprocessedDocuments
Set dc=db.Alldocuments
Set doc = dc.GetFirstDocument
sno=0
Dim count As Variant
count=0
While Not doc Is Nothing
filenames = ws.SaveFileDialog( _
False,"File name",, "E:\samp", ".csv")
If Not(IsEmpty(filenames)) Then
REM Write Body item to file
fileNum% = FreeFile()
Open filenames(0) For Output As fileNum%
headerString ="S.No,UNID,NAME,STATUS,TIME"
header = Split(UCase(headerString),",")
Print #fileNum%, headerString
Do Until doc Is Nothing
If (CStr(doc.Getitemvalue("Status")(0)="Accepted")) Then
sno=sno+1
d=sno+","+doc.Universalid+","+doc.Getitemvalue("Uname")(0)+","+doc.getitemvalue("Status")(0)+","+doc.Getitemvalue("Time")(0)
Print #fileNum%,d
flag=0
Else
flag=1
End If
Set doc = dc.Getnextdocument(doc)
count=count+1
Loop
Else
End If
Wend
If (flag="1") Then
MsgBox"no documents were accepted"
Else
MsgBox "Document exported successfully"
End If
Close fileNum%
End Sub
Your code is unnecessarily complex and has an additional loop that is not necessary at all: You have an outer "while"- loop that does... nothing and an inner "Do until"- loop that really does the looping.
Just replace the outer loop by an If, then you will only be prompted ONCE...
Instead of
While Not doc Is Nothing
filenames = ws.SaveFileDialog( _
False,"File name",, "E:\samp", ".csv")
If Not(IsEmpty(filenames)) Then
...
Do Until doc Is Nothing
...
Loop
End If
Wend
Just write
If Not doc Is Nothing
filenames = ws.SaveFileDialog( _
False,"File name",, "E:\samp", ".csv")
If Not(IsEmpty(filenames)) Then
...
Do Until doc Is Nothing
...
Loop
End If
End If
If Not(IsEmpty(filenames)) Then
'<code removed for brevity>
Else
set doc = nothing
End If
Put an else statement in as above, this way when you send no file name, the doc is set to nothing and the while loop exits.
Related
I'm trying to generate a csv file from lotus notes. Is it possible to get field values from form using freefile? In my case the views doesn't show all the fields which i'm looking for. I have referred some of the sites but no answer. Please help me.
Thanks in advance
I have tried this code atleast to print header but its not working
Dim db As NotesDatabase
Dim uiview As NotesUIView
Dim vw As NotesView
Dim doc As NotesDocument
Dim form As NotesForm
Dim session As NotesSession
Dim Field As NotesItem
Dim fileName As variant
Dim Date1(1 To 3) As String
Dim headerString As String
Dim header As Variant
Dim fieldString As String
Dim fieldList As Variant
Dim i As Long, j As Long,seqno As Integer,count As Long
Dim fileNum As Integer
Dim rowstring As String
Dim cns As String
Sub Initialize
Set uiview = ws.CurrentView
Set view = uiview.View
Set session=New NotesSession
Set db = session.CurrentDatabase
fileName = ws.SaveFileDialog(False,"File name",, "E:\samp" & ".csv")
Call Exit_Form(db)
End Sub
Function Exit_Form(db As NotesDatabase)
fileNum% = FreeFile()
Open fileName For Output As fileNum%
On Error GoTo errorhandler
headerString ="UNID,S.No,SectionName,Year,Discount,Formula,Final Price"
header = Split(UCase(headerString),",")
Set form=db2.Getform("Form1")
i=1
j=1
count1=0
ForAll a In header
Print #fileNum%, a
End ForAll
errorhandler:
MsgBox "ExitForm function" +Error + CStr(Erl)
Exit Function
End Function
You are using the wrong classes.
A "Form" is a design element to show "Documents" in a NotesDatabase. There is no information about the data in there.
You need to get NotesDocument- Objects, and from there you can read the data using GetItemValue- Method.
In addition I would not use the "antique" technique of freefile but use the class "NotesStream" for it.
To e.g. export all documents in a database (means: all different forms are used) you can do something like:
Dim ses as New NotesSession
Dim db as NotesDatabase
Dim dc as NotesDocumentCollection
Dim doc as NotesDocument
Dim stream as NotesStream
Dim lineInFile as String
Dim itemList as Variant
Dim i as Integer
Set db = ses.CurrentDatabase
Set dc = db.AllDocuments
Set stream = ses.CreateStream
....
Call stream.Open( fileName )
Call stream.WriteText( headerLine, EOL_CRLF )
itemList = Split( "ItemFromDocument1,ItemFromDocument2,...", "," )
Set doc = dc.GetFirstDocument()
While not doc is Nothing
For i = 0 to ubound( itemList )
If i = 0 then
writeLine = Cstr( doc.GetItemValue( itemList(i) )(0) )
Else
writeLine = writeList & "," & Cstr( doc.GetItemValue( itemList(i) )(0) )
End If
Next
Call stream.WriteText( writeLine, EOL_CRLF )
Set doc = dc.GetNextDocument(doc)
Wend
Call stream.Close
You could do the same with all documents in a specific folder or view:
Dim view as NotesView
Set view = db.GetView( "NameOfFolderOrView" )
...
Set doc = view.GetFirstDocument()
While not doc is Nothing
...
Set doc = view.GetNextDocument( doc )
Wend
Beware: This approach is quite ugly. It does not consider multi value fields, it does not escape commas that are probably in one of the field values and it does not have any error handling... but at least it is a start.
In my agent, I try to retrieve all the files that are in the current email. My attached code works fine, except for the images in the body of the email. I manage to retrieve all the files and images that were attached to the email except the pictures that were copied and pasted in the middle of the email text. Here is my code:
Dim session As New NotesSession
Dim doc As NotesDocument
Dim db As NotesDatabase
Dim item As Variant
Dim CurrentDocColl As NotesDocumentCollection
Set db = Session.Currentdatabase
Set CurrentDocColl = db.Unprocesseddocuments
Set doc = CurrentDocColl.Getfirstdocument
While Not doc Is Nothing
Set item = doc.GETFIRSTITEM("Body")
If doc.HasEmbedded Then
ForAll attachment In item.EmbeddedObjects
Call attachment.ExtractFile (pathname & "\" & attachment.Name)
End ForAll
End If
Set doc=CurrentDocColl.Getnextdocument(doc)
Wend
How can I retrieve these images?
Thank you very much for your help
I have an agent that does a lot of that, but it's not short. What you have to do is run the document through an XML DomParser, walk down the DOM tree and when you find a node with "JPEG" or "PNG" in the name (the inline images themselves), stream the data to a file and save it. The code is combination of an agent I found online (which I couldn't find again, otherwise I would give credit) and work I've done. You won't be able to copy/paste this sample code and expect it to work, I've removed things (like declaring variables and supporting functions) for brevity.
Sub Initialize
Dim dxlExp As NotesDXLExporter
Set dxlExp = s.CreateDXLExporter
Call dxlExp.setInput(Doc)
Set DomParser=s.CreateDOMparser()
Call DomParser.Setinput(dxlExp)
Dim dxlImp As NotesDXLImporter
Set dxlImp = s.Createdxlimporter()
Call dxlImp.Setinput(domParser)
Call dxlImp.SetOutput(db)
On Event PostDomParse From DomParser Call DomInputProcessed
Call dxlExp.Process
End Sub
Sub DomInputProcessed(DomParser As NotesDomParser)
Dim DomNode As NotesDomNode
Set DomNode = DomParser.Document
Call walkTree(DomParser, DomNode)
Exit Sub
End Sub
Sub walkTree (DomParser As NotesDOMParser, node As NotesDOMNode)
Select Case node.NodeType
Case DOMNODETYPE_DOCUMENT_NODE: ' If it is a Document node
domParser.Output( "<?xml version='1.0' encoding='utf-8'?>"+LF )
Set child = node.FirstChild ' Get the first node
Dim numChildNodes As Integer
numChildNodes = node.NumberOfChildNodes
While numChildNodes > 0
Set child = child.NextSibling ' Get next node
numChildNodes = numChildNodes - 1
Call walkTree(DOMParser, child)
Wend
Case DOMNODETYPE_DOCUMENTTYPE_NODE: ' It is a <!DOCTYPE> tag
domParser.Output("<!DOCTYPE "+ node.NodeName+ ">" + LF)
Case DOMNODETYPE_TEXT_NODE: ' Plain text node
value = xmlReplace(node.NodeValue)
domParser.Output(value)
Case DOMNODETYPE_ELEMENT_NODE: ' Most nodes are Elements
Select Case node.NodeName
Case "jpeg"
Dim jpegfile As String
' Step 1, write the MIME file
Dim base64node As NotesDOMNode
Set base64Node = node.Firstchild
Dim base64Out As NotesStream
Set base64Out = s.createStream()
Dim bytesWritten As Long
bytesWritten = base64Out.Writetext(base64Node.NodeValue)
' Step 2, Read the MIME file and decode it.
Set db=s.currentdatabase
Set doc=db.createDocument()
Set m=doc.Createmimeentity("Image1")
Call m.setContentFromText(base64Out, "image/jpeg", 1727)
Call m.Decodecontent()
Dim JPEGOut As NotesStream
Set JPEGOut = s.createStream()
jpegFile = RandomFileName(baseDir, ".jpg")
JPEGOut.open(jpegFile)
Call m.Getcontentasbytes(JPEGOut, True)
Call JPEGOut.Close()
attachmentNamesStr = attachmentNamesStr + jpegFile + "~"
' Step 3, remove the jpeg and its child node
' We do this by just not sending anything to the DomParser output.
Case "png"
' Same as JPEG except it's PNG.
End Select
End Select 'node.NodeType
End If 'Not node.IsNull
End Sub
I already ask "How to move documents from the original NSF to another NSF?"
(Domino Notes)How to move documents from the original NSF to another NSF?
Now, I still want to ask "How to move the document back to the original NSF?"
I want to make the form that can be moved back to the original database, but there is an error in the command, and cannot be moved back.
The following instructions are written in the buttons of the NOTES form.
How can I modify them?
Sub Click(Source As Button)
Dim ws As New notesuiworkspace
Dim uipr As NotesUIDocument
Dim ask_me As Variant
Set uipr = ws.CurrentDocument
data(0) = "Back original NSF"
data(1) = "Non-person case"
ask_me = ws.Prompt(PROMPT_OKCANCELEDITCOMBO,"Reset Reason","Choose a reason...",data(0),data())
If ask_me = False Then Exit Sub
If uipr.editmode=False Then uipr.editmode=True
If ask_me = data(0) Then
Dim achiveDB As New NotesDatabase("fcpnotesM" , "EFA00B7.nsf")
Dim doc As NotesDocument
Set doc = uipr.Document
Call ChangeField
Msgbox "Change field OK"
Call doc.CopyToDatabase(achiveDB)
Msgbox "Copy success"
Call doc.Remove(True)
Msgbox "Move success"
End If
End Sub
uipr seems to be used before it's defined/asigned
If uipr.editmode=False Then uipr.editmode=True //used here
If ask_me = data(0) Then
Dim achiveDB As New NotesDatabase("fcpnotesM" , "EFA00B7.nsf")
Dim uipr As NotesUIDocument //defined here, but no asignment
I'm trying to search an MS Word doc for embedded Excel files and save them to a different location.
1) I want to record the page number and or section name (based on header style) the embedded file was located in the Word Doc. How can I extract this info?
2) Is there anyway to get the original filename of the embedded Excel file?
Here is the code I'm using to search for embedded files. Originally
Working off the code first presented here: Extract Embeded Excel Workseet Data
Sub TestMacro2()
Application.ScreenUpdating = False
Application.DisplayAlerts = wdAlertsNone
Dim lNumShapes As Long
Dim lShapeCnt As Long
Dim xlApp As Object
Dim wrdActDoc As Document
Dim iRow As Integer
Dim iCol As Integer
Set wrdActDoc = ActiveDocument
For lShapeCnt = 1 To wrdActDoc.InlineShapes.Count
If wrdActDoc.InlineShapes(lShapeCnt).Type = wdInlineShapeEmbeddedOLEObject Then
If wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.ProgID = "Excel.Sheet.8" Then
wrdActDoc.InlineShapes(lShapeCnt).OLEFormat.Edit
Set xlApp = GetObject(, "Excel.Application")
cpath = "location of interest"
xlApp.Workbooks(1).SaveAs cpath & " " & lShapeCnt
xlApp.Workbooks(1).Close
xlApp.Quit
Set xlApp = Nothing
End If
End If
Next lShapeCnt
End Sub
Note: Your code would be more efficient (and easier to read) if you assign an object that's re-used to a variable:
Dim ils as Word.InlineShape
Set ils = wrdActDoc.InlineShapes(lShapeCnt)
(1) The Range.Information method can return the page number. Something like:
Dim pageNumber as Long
pageNumber = ils.Range.Information(wdwdActiveEndPageNumber)
The other option is not as straight forward... I expect you really mean Heading style, not Header style. There is a built-in bookmark that will get the Heading preceding the current selection. That would be something like:
Dim secName as String
ils.Range.Select
secName = ActiveDocument.Bookmarks("\HeadingLevel").Range.Text
(2) If the file is not linked then your chances are slim. There's nothing VBA can get at directly, that's certain. Possibly, something might be stored in the WordOpenXML. You can check that by downloading the Open XML SDK Productivity Tool, opening such a document in it and inspecting that part of the Open XML. If it's in there then you can get at it in VBA using ils.Range.WordOpenXML to get the Open XML for the InlineShape, then parse that.
I want to use the following script library in button and also in agent.
My script library code:Validate
Option Public
Option Declare
Dim Sess As NotesSession
Dim currentDb As NotesDatabase
Dim dataDb As NotesDatabase
Dim doc As NotesDocument
Dim workspace As NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim rtitem As NotesRichTextItem
Sub Initialize
Set Sess = New NotesSession
Set currentDb = Sess.CurrentDataBase
Set workspace = New NotesUIWorkspace
Set uidoc = workspace.CurrentDocument
End Sub
Function ValidateForm ( Source As NotesUIDocument) As Boolean
On Error GoTo e
Set doc=source.Document
Dim Txt As String
Dim trimmed As string
txt = doc.Name(0)
trimmed = Trim(Txt)
If ( trimmed = "") Then
MsgBox "Please enter some text."
source.GotoField("Name")
ValidateForm= false
Else
ValidateForm= True
End If
Exit Function
e:
MsgBox "error at"& Erl() & " and error is "& Error()
End Function
In Button:
In button when i call the script library since in the validateform function it has source as notesuidocument and in button click it has souce as button it i giving me error.
Sub Click(Source As Button)
End Sub
I have tried using in agent in options using below:
Use "Validate"
and tried calling it in button using formula
#Command([ToolsRunMacro]; "Val")
But no use I am not getting the desired output.
I am new to lotus notes.Please help me in doing above tasks.
You don't need to take a parameter at all. In the initialize- Sub of your Script- Library you already set the global variable "uidoc" to the currently opened document:
Set workspace = New NotesUIWorkspace
Set uidoc = workspace.CurrentDocument
In your Function "validateForm" you simply omit the parameter and then replace "source" with "uidoc"
Set doc=source.Document
The other possibility (if you want to give the current document as a parameter):
Sub Click( Source as Button)
Dim ws as New NotesUIWorkspace
Dim uidoc as NotesUIDocument
set uidoc = ws.CurrentDocument
Call ValidateForm( uidoc )
End If
Or if you keep the initialize code in your Library:
Sub Click( Source as Button)
Call ValidateForm( uidoc )
End If
This works, as "uidoc" is a global variable, that is already initialized by the Sub initialize of your Script- Library.
HTH
Make it an agent, not a script library. If it's named Validate, use that formula you had in the button without trying to include a script library.
#Command([ToolsRunMacro]; "Validate")
Script libraries are typically used for subroutines and functions that you will call from multiple agents or other scripts, not for entire agents. You can call an agent from a button or allow users to click on it in the Action menu or any number of other ways of calling it. You don't have to put it in a script library.
You could reduce the code in the agent to be as follows:
Option Public
Option Declare
Sub Initialize
Dim workspace As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Dim Txt As String
Dim trimmed As string
Set uidoc = workspace.CurrentDocument
On Error GoTo e
Set doc=uidoc.Document
txt = doc.Name(0)
trimmed = Trim(Txt)
If ( trimmed = "") Then
MsgBox "Please enter some text."
uidoc.GotoField("Name")
End If
exit sub
e:
MsgBox "error at"& Erl() & " and error is "& Error()
End Sub
Or, if all you want to do is verify that a field is not empty and shift focus to that field, just add the following to any field's Input Validation formula:
#If ( #ThisValue = ""; #Failure ( "You must enter a value for " + #ThisName ); #Success )