Cannot access more than 250 items in a folder

G

gordon

My company has a custom Outlook form for handling vacation and sick
time requests. The form has fields for start date/time, end date/time,
name, etc.

I'm trying to write some code that will process a bunch of saved
requests and display some totals, but I'm having trouble. The code
simply stops working after about the 250th item in a folder. Any
attempt to get at the custom properties of any item after the 250th is
a blank.

Here's some very simple code I wrote to illustrate the problem. It
loops through each saved item and checks if the "requestor" property
contains a capital I. (Our organization has a capital I in the name,
and the org name is appended to everyone's name, so everyone
effectively has a capital I in their name.)

The result of the code *should* be one capital I for every item in the
folder, but it ain't working that way. After about item 247 or so, it
stops working. No further items will register as containing a capital
I in the "requestor" property.

I've found various vague references claiming that this is a known bug,
that you cannot access more than 250 items in a folder, but that seems
preposterous. There must be a way around it.

Can anyone help? Thanks.

Code follows -------------------------------------


Option Explicit

Dim objapp, curr_fldr

Set objapp = CreateObject("Outlook.Application")
Set curr_fldr = objapp.ActiveExplorer.Currentfolder

Sub btnReport_Click()
Dim requestor, itm, itemNumber, Icount, tmpIcount, theLength
Dim idx, myChar, noIcount

On Error Resume Next

Icount = 0
noIcount = 0

For itemNumber = 1 to curr_fldr.Items.Count
Set itm = curr_fldr.Items(itemNumber)
requestor = " "
requestor = itm.UserProperties("Requestor")
theLength = Len(requestor)
tmpIcount = 0
For idx = 1 to theLength
myChar = Mid(requestor, idx, 1)
if myChar = "I" Then
tmpIcount = tmpIcount + 1
End If
Next
if tmpIcount = 0 then
noIcount = noIcount + 1
end if
Icount = Icount + tmpIcount
Set itm = Nothing
Next

MsgBox "Finished reading messages" & vbCrLf & "Icount = " _
& Icount & vbCrLf & "noIcount = " & noIcount
End Sub

Code ends -------------------------------------
 
D

Dmitry Streblechenko

Yes, there is a way around, you just need to make sure that there are no
dangling references to any COM objects, either explicit or implicit in your
code.
That's VB, not VB.Net, right?
I'd start by caching the Item collection in a variable, rather than
retrieving it each time using MAPIFolder.Items:

set Item = curr_fldr.Items
For itemNumber = 1 to Items.Count
...
Set itm = Items.Item(itemNumber)
next

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
J

John Gordon

In said:
Yes, there is a way around, you just need to make sure that there are no
dangling references to any COM objects, either explicit or implicit in your
code.

How do I know if there are any references to COM objects? I'm not very
familiar with Outlook programming; I basically inherited this code from
a developer who has retired. Where would I look for this?
That's VB, not VB.Net, right?
VBscript.

I'd start by caching the Item collection in a variable, rather than
retrieving it each time using MAPIFolder.Items:
set Item = curr_fldr.Items
For itemNumber = 1 to Items.Count
...
Set itm = Items.Item(itemNumber)
next

I tried this, but the loop exited immediately. Are you sure there isn't
a typo here somewhere? You set an object called "Item" in the first line,
but then reference an object called "Items" on the second and fourth lines.
 
D

Dmitry Streblechenko

Yes, it must be "set Items = ...".
Make sure you don't get implicit variables. E.g. when you have something
like

set Obj1 = Obj2.SomeProperty.SomeObjectProp

compiler translates it into

set TempObject= Obj2.SomeProperty
set Obj1 = TempObject.SomeObjectProp

where TempObject is implicitly created by the compiler and is only released
when it goes out of scope (the sub exits)

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
J

John Gordon

In said:
Yes, it must be "set Items = ...".
Make sure you don't get implicit variables. E.g. when you have something
like
set Obj1 = Obj2.SomeProperty.SomeObjectProp
compiler translates it into
set TempObject= Obj2.SomeProperty
set Obj1 = TempObject.SomeObjectProp
where TempObject is implicitly created by the compiler and is only released
when it goes out of scope (the sub exits)

This does shed some light on why it is happening, but the problem still
won't go away. I've tried everything I can think of.

Here's the latest version of my example program, which simply looks at
the "Requestor" property and verifies that the length is greater than 1
(which it is for every item).

Option Explicit

Dim objapp, curr_fldr, activeExp

Set objapp = CreateObject("Outlook.Application")
Set activeExp = objapp.ActiveExplorer
Set curr_fldr = activeExp.Currentfolder

Sub btnReport_Click()
Dim requestor, itm, itemNumber, goodNames, badNames, theLength
Dim itemList

goodNames = 0
badNames = 0
set itemList = curr_fldr.Items

For itemNumber = 1 to itemList.Count
Set itm = itemList(itemNumber)
requestor = itm.UserProperties("Requestor")
theLength = Len(requestor)
if theLength > 1 then
goodNames = goodNames + 1
else
badNames = badNames + 1
end if
requestor = " "
Set itm = Nothing
Next

MsgBox "Finished reading messages" & vbCrLf & "good names = " _
& goodNames & vbCrLf & "bad names = " & badNames
End Sub

What am I doing wrong here? I'm not accessing any deeply-nested properties
such as were in your example, and the "itm" object gets released at the
end of every pass of the loop.

Thanks for any replies.
 
D

Dmitry Streblechenko

You are still causing implicit variables to be created:

requestor = itm.UserProperties("Requestor")

which is really

requestor = itm.UserProperties.Items("Requestor")

UserProperties becomes an implicit variable.
Try to comment out everything in the loop but the
Set itm = itemList(itemNumber)
statement. If that works, move all the code inside the loop to a separate
sub - this way all variables will become local to that sub and will be
released automatically as soon as the sub exits

For itemNumber = 1 to itemList.Count
Set itm = itemList(itemNumber)
SubThatDoesAllTheWork(itm)
Set itm = Nothing
Next


Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
J

John Gordon

In said:
You are still causing implicit variables to be created:
requestor = itm.UserProperties("Requestor")
which is really
requestor = itm.UserProperties.Items("Requestor")
UserProperties becomes an implicit variable.
Try to comment out everything in the loop but the
Set itm = itemList(itemNumber)
statement. If that works, move all the code inside the loop to a separate
sub - this way all variables will become local to that sub and will be
released automatically as soon as the sub exits
For itemNumber = 1 to itemList.Count
Set itm = itemList(itemNumber)
SubThatDoesAllTheWork(itm)
Set itm = Nothing
Next

I tried that, and I am still having the same problem. Is VBScript
different in this regard from "normal" Visual Basic? Anyway, here's the
latest code, which is crashing on the "set props = theItem.userProperties"
line in the ProcessItem() subroutine:

Option Explicit

Sub btnReport_Click()
Dim itm, itemCount, itemNumber, itemList
Dim objapp, curr_fldr

Set objapp = CreateObject("Outlook.Application")
Set curr_fldr = objapp.ActiveExplorer.Currentfolder
set itemList = curr_fldr.Items
itemCount = itemList.Count

For itemNumber = 1 to itemCount
Set itm = itemList(itemNumber)
processItem(itm)
Set itm = Nothing
Next

MsgBox "Finished reading messages" & vbCrLf _
& "itemNumber is " & itemNumber
End Sub

Sub processItem(theItem)
Dim props

set props = theItem.userProperties
set props = Nothing
End Sub
 
D

Dmitry Streblechenko

What is yout version of Outlook? I had no problem runnign the following
script using OutlookSpy (click "Script Editor", paste the script, clcick
Run) in Outlook 2003 SP2 using online Exchange store.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Dim itm, itemCount, itemNumber, itemList
Dim objapp, curr_fldr

Set objapp = CreateObject("Outlook.Application")
Set curr_fldr = objapp.ActiveExplorer.Currentfolder
set itemList = curr_fldr.Items
itemCount = itemList.Count

For itemNumber = 1 to itemCount
Set itm = itemList.Item(itemNumber)
processItem(itm)
Set itm = Nothing
Next

MsgBox "Finished reading messages" & vbCrLf _
& "itemNumber is " & itemNumber

Sub processItem(theItem)
Dim props

if theItem.Class = 43 then
set props = theItem.userProperties
debug.print props.Count & " " & theItem.Subject
End If

set props = Nothing
End Sub
 
J

John Gordon

In said:
What is yout version of Outlook? I had no problem runnign the following
script using OutlookSpy (click "Script Editor", paste the script, clcick
Run) in Outlook 2003 SP2 using online Exchange store.

I'm using Outlook 2003 (11.6359.6360) SP1. When you ran it, was it in a
folder that had more than 250 items?

Dim itm, itemCount, itemNumber, itemList
Dim objapp, curr_fldr
Set objapp = CreateObject("Outlook.Application")
Set curr_fldr = objapp.ActiveExplorer.Currentfolder
set itemList = curr_fldr.Items
itemCount = itemList.Count
For itemNumber = 1 to itemCount
Set itm = itemList.Item(itemNumber)
processItem(itm)
Set itm = Nothing
Next
MsgBox "Finished reading messages" & vbCrLf _
& "itemNumber is " & itemNumber
Sub processItem(theItem)
Dim props
if theItem.Class = 43 then
set props = theItem.userProperties
debug.print props.Count & " " & theItem.Subject
End If
set props = Nothing
End Sub

I installed OutlookSpy and entered this script, and it ran for a little
while, and then I got this information dialog:

The add-in "C:\Program Files\OutlookSpy\OutSpy.dll" could not be
installed or loaded. This problem may be resolved by using Detect
and Repair on the Help menu.

I clicked OK, and the script continued to run, but the same dialog would
pop up after every record. This went on for a little while longer, and
then I got this error dialog:

Error executing script: Line 22, Column 17

Line 22 is the "set props = theItem.userProperties" line. Grrr!

Any suggestions? I appreciate your help, Dmitry.
 
D

Dmitry Streblechenko

Yes, I ran it in a folder with 700+ items... Any chance you can install SP2
and see if it behaves any better?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
J

John Gordon

In said:
Yes, I ran it in a folder with 700+ items... Any chance you can install SP2
and see if it behaves any better?

I installed SP2, and it made no difference. The script still crashes on
the "set props = theItem.userProperties" line.
 
J

John Gordon

In said:
Both in your VB code in OutlookSpy script?

Yes, both.

I received a private email from someone telling me that they had similar
problems, and they solved it using
System.Runtime.InteropServices.Marshal.ReleaseComObject. It didn't help
me, though.
 
D

Dmitry Streblechenko

ReleaseComObject is only for .Net
Do you have any third-party add-ins installed? Any chance you can try this
on a clean machine?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
J

John Gordon

In said:
ReleaseComObject is only for .Net
Do you have any third-party add-ins installed?

No, not that I know of.
Any chance you can try this on a clean machine?

I might be able to. The machine I'm thinking of won't have a folder full
of hundreds of custom form items, though. What's the best way to get lots
of these items? Can I copy them from the machine I'm using now?
 
D

Dmitry Streblechenko

You can just create a dozen or so messages in one folder, then select them
all and drag to the traget folder while holding the Ctrl key.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top