I Delete control array element using Unload and try to replace element using following code
Private Sub mnudelete_Click()
Dim i As Integer
MsgBox (SelectedItemIndex)
RoomIndex = SelectedItemIndex
Unload frmData.lblRoom(RoomIndex)
Unload frmData.brdrRoom(RoomIndex)
For i = SelectedItemIndex To NumberOfRooms
lblRoom(i) = lblRoom(i + 1)
brdrRoom(i) = brdrRoom(i + 1)
Next
NumberOfRooms = NumberOfRooms - 1
End Sub
but some error occurred, is it possible to perform delete in control array?
help me plz :)
You can only remove controls in a Control Array if you added them at runtime (try to delete one that you added via the designer and you'll get an error). This code should work:
Unload lblRoom(RoomIndex)
Unload brdrRoom(RoomIndex)
From MSDN:
You can use the Unload statement to remove any control created with Load. However, you cannot use Unload to remove controls created at design time, regardless of whether or not they are part of a control array.
Related
The problem I am encountering is that some of the messages are not accessible by the user ID file, I would like to skip these files instead of the agent crashing out. The error message received is as follows:
Using the view approach if this happened I was able to delete the document temporarily and re-run the agent but if there is a way to skip documents it would be a great help.
Thanks for the help guys.
Ok I have amended the code to a point where I am almost comfortable with it.
Sub Initialize
Dim s As New notessession
Dim db As notesdatabase
Dim view As notesview
Dim doc As notesdocument
Dim nextdoc As notesdocument
Set db = s.currentdatabase
If view Is Nothing Then
Set view = db.CreateView("Encrypted",{Encrypt="1"})
End If
Set doc = view.getfirstdocument
On Error Goto ErrorHandler
While Not doc Is Nothing
nextDocument:
Set nextdoc = view.getnextdocument(doc)
'The below loop is mandatory to ensure that all $File entries are unecrypted
Forall i In doc.items
If i.isencrypted Then
i.isencrypted=False
End If
End Forall
'Must have at least 1 field encrypted in order to call Encrypt method
Dim temp As New NotesItem(doc,"tempjunk","temp")
temp.IsEncrypted=True
Call doc.encrypt
Call doc.save(True, False)
'This portion can now remove the fields relative to encrypting the
'single token encrypted field.
Call doc.removeitem("$Seal")
Call doc.removeitem("$SealData")
Call doc.removeitem("SecretEncryptionKeys")
Call doc.removeitem("Encrypt")
Call doc.removeItem("tempjunk")
Call doc.save(True, False)
Set doc = nextdoc
Wend
Exit Sub
ErrorHandler:
On Error Resume nextDocument
Exit Sub
End Sub
The error handling is not playing nice;
On Error Resume nextDocument is showing up as an error.
I have tried suppressing all of the error warnings which seems to attempt to strip the encryption but I think they body of the messages is being destroyed as a result.
It is no problem to create an agent in a container database and let that agent access documents in all "target" databases and modify them accordingly - No need to copy that agent to all databases.
Only restriction: If the databases are on another server, then on the server security tab of the target server you have to enter the server with the container database as trusted server.
AND: If your agent runs longer than the allowed maximum run time for agents on the server, then it will be killed prematurely.
There is no need to create views in the target databases, you can use NotesDatabase.Search() to get the corresponding documents in the databases...
You can create views by copying them from another database. Say you create a view "Encrypted" in your db with the agent.
Then add a piece of code to get a handle of this view as a NotesDocument:
Dim dbThis As NotesDatabase
Dim viewTemplate As NotesView
Dim docView As NotesDocument
Set dbThis = s.currentDatabase
Set viewTemplate = dbThis.getView("Encrypted")
Set docView = dbThis.Getdocumentbyunid(viewTemplate.Universalid)
In the agent loop, test if view Encrypted exists, if not copy the "view template":
Set view = db.getview("Encrypted")
If view Is Nothing Then
Call docView.Copytodatabase(db)
Set view = db.getview("Encrypted")
End If
Finally, if you insist, a similar procedure might be used to copy the agent to all databases, but for me the idea of running the agent in one db sounds better.
Edited: In the view of full disclosure - of course you can create a view (I guess that was the original question).
If view Is Nothing Then
Set view = db.Createview("Encrypted", {Encrypt="1"})
End If
Or do one-shot dbSearch suggested by Torsten, with a good re-mark of Richard - if you intend to run your code several times - say if encrypted documents might get created again or re-encrypted, rather go for the view.
My method is a bit old fashioned (pre-dates availability of createView) and works well if you need more than selection formula, so you can pre-build a complicated view for re-use.
Performance-wise: whatever method you will choose either creating view using createView or copying from other db or doing dbSearch there is going to be a certain slow-down while the view gets built or dbSearch executes. Karl-Henry's approach will avoid this search/view build, but will be relatively slow if there are not many encrypted documents.
Whichever method you choose - here is a small tip to boost performance. Make your loops like this to release memory as you go; for example, assuming Karl-Henry's approach:
Dim doc1 as NotesDocument
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
Set doc1 = col.GetNextDocument(doc)
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
' releasing memory when processing thousands of documents improves performance and avoids crashes
Delete doc
Set doc = doc1
Loop
Now again, as you are talking only about migration (so one shot) of 20+ databases, the speed or implementation details should not be that critical.
If you have to process all (or almost all) documents in each database, you can use db.AllDocuments. It is more efficient than using db.Search() with an #All formula.
If you want to exclude certain documents, perhaps based on the form name, I would build a list of forms to exclude, and then use IsElement to check each document being processed against that list.
Dim exclude List As Boolean
exclude("FormA")=True
exclude("FormB")=True
Set col = db.AllDocuments
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
Set doc = col.GetNextDocument(doc)
Loop
Something like that. By the way, you can create the list as any data type. I just choose Boolean as it is a small data type, and that it makes the code easier to read. The IsElement() function just check if the element exists, it does not use the value you set.
You would wrap the code above in a function and call it once per database.
Appended answer, based on additional info in original question:
That should not be hard, just add error handling to your code.
Before you start to loop throung the document:
On Error Goto errHandler
Before you get the next document in the loop:
nextDocument:
At the end of your code:
Exit Sub
errHandler:
Resume nextDocument
End Sub
Try that.
I am trying to automate a process to update a wise for windows package at compile time to update the productcode, package code, productversion, and the update table versionmax values.
I can successfully update the property table and the summary information for the Package Code. However, the update table is giving me problems. There are several entries in this table.
I can enumerate the existing entries, but I cannot update the existing entries. Each time I attempt to I get an error "Exception: Object required 'project.WTables(...).WRows.Row(...)'
The syntax I am using is identical to the preceding calls to update the ProductCode, ProductVersion, and Package Code.
I am using vbscript.
I am passing in the product version and full path to the wise wsi project file. In the UpdateUpgradeTable function aUpgradeGuids populate correctly with a collection of upgrade codes as I expect. All I want to do now is to change the VersionMax value for each of these codes to the current wiseProductVersion. However, vbscript seems to have some problem with the object WRows.Row(a(i)), which is an actual GUID.
I have looked at other sample scripts in the automation section of help and it does support the use of variables, and it does not look like the variables require quotes like straight text does. I am not even sure what it means, object required. Project is definitely an object. I have confirmed that. I have even tried this by inserting straight text inside the function but it still fails. I have tried it with tblProperty.WRows.Row(...) but it fails the same way. I have tried calling it with a good Upgrade Code outside of the For loop right after Set tblProperty = ... and it still fails. This type of structure works in all previous tables. It has me puzzled. Any ideas? I think this may transcend just Wise for Windows and is perhaps generic to msi as well so I am going to post under MSI too.
I have a sub main that looks like this:
Dim wiseInstallDir: wiseInstallDir = WScript.Arguments(0)
Dim wiseProductVersion: wiseProductVersion = WScript.Arguments(1)
Sub main()
Set wise = CreateObject("WfWi.Document")
Dim nResult
nResult = wise.Open (wiseInstallDir)
UpdateProductVersion wise
... 'other functions
UpdateUpgradeTable wise
wise.Save wiseInstallDir
End Sub
'This function works properly
Sub UpdateProductVersion(project)
Set tblProperty = project.WTables("Property")
tblProperty.WRows.Row("ProductVersion").WColumns("Value").Data=wiseProductVersion
End Sub
Sub UpdateUpgradeTable(project)
Set tblProperty = project.WTables("Upgrade")
Dim tmpRow,count: count = 0
Dim aUpgradeGuids: Set aUpgradeGuids = CreateObject("Scripting.Dictionary")
Const UPGRADECODE = 0
For Each tmpRow In tblProperty.WRows
Dim tRow: tRow=tmpRow.Key
Dim values: values=Split(tRow, ",")
aUpgradeGuids.Add count,values(0)
count=count + 1
Next
a = aUpgradeGuids.Items
For i = 0 To aUpgradeGuids.Count - 1
project.WTables("Upgrade")._
WRows.Row(a(i)).WColumns("VersionMax").Data=wiseProductVersion
Next
End Sub
main
EDIT:
'updated UpdateUpgradeTable
Sub UpdateUpgradeTable(project)
Set tblProperty = project.WTables("Upgrade")
Dim tmpRow
'Get the UpgradeCode for each current record and change the VersionMax value for that record.
For Each tmpRow In tblProperty.WRows
Dim tRow: tRow=tmpRow.Key
Dim values: values=Split(tRow, ",")
tblProperty.WRows.Row(values(0)).WColumns("VersionMax").Data=wiseProductVersion
Next
End Sub
I think I know the answer. I still do not have it working 100% but I found additional documentation for the Row method stating for tables with multiple key columns, commas separate key values. I have inserted the value(0), value(1), ... but I am now getting a different error. I will update once I get this working.
The upgrade table has 5 primary key values.
<!-- language: lang-vbs -->
Set rows = tblProperty.WRows
Set row = tblProperty.WRows.Row(values(UPGRADECODE), values(VERSIONMIN), values(VERSIONMAX), values(LANGUAGE), values(ATTRIBUTES))
tblProperty.WRows.Row(values(UPGRADECODE),values(VERSIONMIN),values(VERSIONMAX),values(LANGUAGE),values(ATTRIBUTES)).WColumns("VersionMax").Data=wiseProductVersion
Note that the first Set rows=... returns a valid object with its corresponding methods.
The second line fails with the message:
Exception: Wrong number of arguments or invalid property assignment: 'tblProperty.WRows.Row'
Below are the 5 primary keys for the upgrade table.
values (UPGRADECODE)
values (VERSIONMIN)
values (VERSIONMAX)
values (LANGUAGE)
values (ATTRIBUTES)
Is there another way to update the upgrade table? Is there something I am missing?
According to documentation the WRows object is a child of WTable. And it is returning a valid object for me. It has the following method:
WRow Row(BSTR strKeyValue): returns a WRow given its key value. For tables with multiple key columns, commas separate key values.
Row() is the default method.
However, my comma separated key values construct above is failing and I am not sure where to turn now. Has anyone ever worked with this before and had it working?
I have copied my entire vb6 code from one machine to another , now when i was running my code on another machine ,it shows error like : compile error : procedure declaration does not match description of event or procedure having the same name,
This is the code :
Private Sub MKDataGrid1_KeyPress()
If MKDataGrid1.Col = 0 Or MKDataGrid1.Col = 1 Or MKDataGrid1.Col = 2 Or MKDataGrid1.Col = 3 Then
MKDataGrid1.AllowUpdate = False
MsgBox "This field is not to edit. Thnks"
MKDataGrid1.AllowUpdate = False
cmdAdd.visible = True
cmdAdd.SetFocus
cmdAdd.visible = False
Else
MKDataGrid1.AllowUpdate = True
End If
End Sub
It looks like your declaration for the event got messed up. Generally speaking, the KeyPress event takes the parameter KeyAscii As Integer. I recommend temporarily remarking out your routine and then selecting the KeyPress event manually from the dropdown in the code window. Then copy your previous content back into the KeyPress that VB inserted.
I have to register the vb6datagrid.ocx on my computer for this , i have register this .ocx on my machine , actually i have again copy the new code in my machine from my old machine and before runing it i have open Project >> components >> designers and from there selected the require components and have removed the unwanted , and then i have run the project so again i get the error but when i go to view object there again i find the object missing so i have placed the datagrid and then its running fine :)
I want to notify the user of the macro if something went wrong during the execution of the macro. I was wondering if it would be possible to add an item to the Visual Studio error list?
It is possible to do so from within an AddIn (like here), but I would like to do the same thing from a macro.
Edit
To further clarify what i want to achive, here is the sample from the Samples macro library (Alt+F8 -> Samples -> Utilities -> SaveView())
Sub SaveView()
Dim name As String
name = InputBox("Enter the name you want to save as:", "Save window layout")
If (name = "") Then
MsgBox("Empty string, enter a valid name.")
Else
DTE.WindowConfigurations.Add(name)
End If
End Sub
Instead of the MsgBox("...") alert I want to put the error into the VS error list.
You can add an item in the Task List easily from your macro. Just use the AddTaskToList method from that article and change m_objDTE to DTE. I've tried it and it worked.
However, adding the item in Error List, is probably impossible. You need to call VS services, see how adding an error is done in an add-in. I created a macro from this code and it didn't work. In general, VS services don't work in macros. I was able to create ErrorListProvider successfully. I could access it's methods and properties. But calling ErrorListProvider.Task.Add caused COM exception. If you want to play with it, several notes:
As described in the article, you need to get 4 assemblies out of the GAC e.g. to c:\dlls\ directory. Since Macros IDE doesn't allow you to browse when you Add Reference, you need to copy these dlls into ...\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies directory (change the 10.0 to your VS version). Then, when you Add Reference in Macros IDE, you should see the assemblies.
The GetService function always returned Nothing. Add the following field to the class:
Private serviceProvider As IServiceProvider = New Microsoft.VisualStudio.Shell.ServiceProvider(CType(DTE, Microsoft.VisualStudio.OLE.Interop.IServiceProvider))
and in GetService function change line:
objService = Microsoft.VisualStudio.Shell.Package.GetGlobalService(serviceType)
to
objService = serviceProvider.GetService(serviceType)
As I wrote, everything seems OK then but ErrorListProvider.Task.Add fails.
I think that for your situation outputting something to your own output pane would be more suitable. The error list is generally used for errors within the project the user is working on, not for errors caused by running macros. Especially when someone says it can't be done. :)
Outputting to your own output pane is pretty easy:
DTE.Windows.Item(Constants.vsWindowKindOutput).Activate()
Dim panes As OutputWindowPanes = window.OutputWindowPanes
Dim my_pane As OutputWindowPane
Try
my_pane = panes.Item("SaveView")
Catch exception As System.ArgumentException
my_pane = panes.Add("SaveView")
End Try
my_pane.Activate()
my_pane.OutputString("Empty string, enter a valid name." + vbCrLf)
Hope this helps.
Cheers,
Sebastiaan
Is this not what you want?
HOWTO: Add an error with navigation to the Error List from a Visual Studio add-in
http://www.mztools.com/articles/2008/MZ2008022.aspx
I have an Image object.
I have the Picture type set to linked, so I can change the picture if I want.
I have the Picture property set to the picture name.
I would think that access would use relitive addressing and simple looking in the current directory for the image. But it does not and I get an error telling me it cannot find the picture.
Anyone have a solution? (Other than setting the Picture type to embedded or using the full file address?)
Thanks!
Update:
Tried this:
Private Sub Form_Load()
Dim file As String
file = CurrentDb().Name
file = Replace(file, ".mdb", ".bmp")
Me.Image46.Picture = file
End Sub
It works, except I still get the error message. I click O.K. and it works. Just need the error message to go away.
SOLUTION: Use the above code (or the code posted in the answer below) and then set the 'picture type' to "embedded" and then delete the 'picture' field so that it says "(none)".
Save and run.
It should work.
THANKS!
You could set the property on the forms OnLoad event like this
Me.imgMy_image.picture=getDBPath & “mypicture.bmp”
Here is the getDBPath function
Public Function GetDBPath() As String
Dim strFullPath As String
Dim I As Integer
strFullPath = CurrentDb().Name
For I = Len(strFullPath) To 1 Step -1
If Mid(strFullPath, I, 1) = "\" Then
GetDBPath = Left(strFullPath, I)
Exit For
End If
Next
End Function
Before anyone comments yes I know in access 2000 and above you can use currentproject.path but I’m stuck in the land that time forgot so need that custom function, it still works with later versions of access
Current folder depends of the way you open database in Access. At least, if you open it thru "File-Open", current folder changes to the folder of MDB file. But if you open via double-clicking MDB in explorer, it does not.