Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

making parameters optional in custom VB component 2

Status
Not open for further replies.

Programmer1974

Programmer
Feb 19, 2004
33
US
Hello all! I thought about posting this in the XML forumn, but after browsing through there, I think I might have better luck trying here first...

I'm creating my own custom components (.wsc extension) and have included a method where I want to make some of the parameters optional. Below is how I call the method and the component I created. This component is just for experimental purposes. It basically creates a CDO message and sends an e-mail via SMTP. As most of you know, the only required fields are the from and to addresses. I want to apply the same rules to my method. Here is how I call the method now:
Code:
Set objSMTP = CreateObject("SMTP")
strReturn = objSMTP.SendNote("test@email", "test@email", "", "", "Test subject", "Test message", "", "")
Here is how I want to call the method:
Code:
Set objSMTP = CreateObject("SMTP")
strReturn = objSMTP.SendNote("test@email", "test@email")
Or even perhaps this:
Code:
Set objSMTP = CreateObject("SMTP")
strReturn = objSMTP.SendNote("test@email", "test@email", , , "Test subject", "Test message")

Here is the component:
Code:
<package>
<?component error="true" debug="true"?>

	<comment>
		This component is used to send an e-mail via SMTP.
	</comment>

	<component id="SMTPEMail">
		<object id="objEmail" progid="CDO.Message"/>
	
		<registration
			progid="SMTP"
			description="This component sends an e-mail message via SMTP."
			version="1.0"
			clsid="{21D2D7E7-A67D-4B97-9F71-C027E173FC23}"/>
		
		<public>
			<method name="SendNote">
				<parameter name="From" internalName="strFrom" />
				<parameter name="To" internalName="strTo" />
				<parameter name="CC" internalName="strCC" />
				<parameter name="BCC" internalName="strBCC" />
				<parameter name="Subject" internalName="strSubject" />
				<parameter name="Body" internalName="strTextBody" />
				<parameter name="HTMLBody" internalName="strHTMLBody" />
				<parameter name="Attachments" internalName="strAttachments" />
			</method>
		</public>
		
		<script language="VBScript">
			Function SendNote(strFrom, strTo, strCC, strBCC, strSubject, strTextBody, strHTMLBody, strAttachments)
				objEmail.From = strFrom
				objEmail.To = strTo
				objEmail.CC = strCC
				objEmail.BCC = strBCC
				objEmail.Subject = strSubject
				
				If strTextBody > "" Then
					objEmail.TextBody = strTextBody
				Else
					objEmail.HTMLBody = strHTMLBody
				End If
				
				If strAttachments > "" Then
					objEmail.AddAttachment strAttachments
				End If
			
				objEmail.Configuration.Fields.Item ("[URL unfurl="true"]http://schemas.microsoft.com/cdo/configuration/sendusing")[/URL] = 2
				objEmail.Configuration.Fields.Item ("[URL unfurl="true"]http://schemas.microsoft.com/cdo/configuration/smtpserver")[/URL] = "[SMTP server]"
				objEmail.Configuration.Fields.Update
				
				On Error Resume Next
				objEmail.Send
				
				SendNote = Err.Number
			End Function
		</script>
	</component>
</package>

How can I modify my component to allow for optional parameters?

Thank you all for your help! If I don't have any luck here, I will try the XML forumn.
 
I'm not sure what help the XML forum might be.

Note that you're writing VBScript and not VB.

VBScript does not directly (or fully) support Optional parameters in its Functions/Subs. There is a workaround that can be useful in simulating this at times. It is described in the documentation but it can be hard to root out.

I believe it has limitations though. There is no syntax I'm aware of that will let you call a VBScript Function or Sub omitting the final parameter.

OptParam.vbs
Code:
Option Explicit

Dim strVar

Sub SomeSub(ByVal Required, ByRef RefOptParam, ByVal ValOptParam)
  Dim ROPTemp

  'Handle Optional ByRef on entry.
  If VarType(RefOptParam) = vbError Then
    ROPTemp = "Ref default value"
  Else
    ROPTemp = RefOptParam
  End If

  'Handle Optional ByVal on entry.
  If VarType(ValOptParam) = vbError Then
    ValOptParam = "Val default value"
  End If

  MsgBox Required & ": " & ValOptParam & ", " & ROPTemp
  ROPTemp = "New value"

  'Handle Optional ByRef on exit.
  If VarType(RefOptParam) <> vbError Then
    RefOptParam = ROPTemp
  End If
End Sub

'Syntax errors!
'SomeSub "Both left out"
'SomeSub "Both left out", , 

strVar = "Ref"
SomeSub "Both supplied", strVar, "Val"
MsgBox strVar

SomeSub "2nd left out", , "Val"
Please note that for Optional ByRef parameters that hold object references you'll need to use Set statements instead of Let statements (simple assignments) in the entry/exit hacks.

ByVals have an implied temporary you can assign a default value to, while for ByRefs you'll need to declare temporaries explicitly.
 
Thanks for the response dilettante! Interesting solution, but like you mentioned, VB Script is rather limited with this. I was hoping that XML had a way to specify a default value if the parameter was not passed in or something goofy like that.

I'll try posting this in the XML forumn and see what happens. Thanks all for your consideration!
 
Programmer1974,

For wscript/cscript host, it exposes a named argument collection. It does not for sub and functions.

[1] Nevertheless, you can achieve the same objective and more to your favour by passing dictionary object.
[tt]
<script language="VBScript">
Function SendNote(odic)
if typename(odic)<>"Dictionary then
'show usage
'exit function or other alternative
end if
'be careful, item name is case sensitive
with objEmail
.From = odic.item("From")
.To = odic.item("To")
.CC = odic.item("CC")
.BCC = odic.item("BCC")
.Subject = odic.item("Subject")
if .From = "" then .From = "some default From value"
if .To = "" then .To = "some default To value"
'etc etc
end with
'continue with the other lines
End Function
[/tt]
[2] To call the function, do this, and it is how you want it be called.
[tt]
Set objSMTP = CreateObject("SMTP")
set odic = createobject("scripting.dictionary")
'be carefully of consistency of key name's cases
odic.add "From", "test@email"
odic.add "To", "test@email"
strReturn = objSMTP.SendNote(odic)
set odic = nothing
[/tt]
Whenever undefined key, the function will retrieve an empty (vbEmpty), and the function knows how to handle. Same for inclusion or omission of other arguments.

[3] When compare with empty string, I would prefer "<>" rather than ">" or "<". It is not only a style, a matter of personal taste, it also makes more logical sense.

regards - tsuji
 
Correction (typos)
[tt] if typename(odic)<>"Dictionary[red]"[/red] then[/tt]
- tsuji
 
-Further Notes-

Upon re-reading your construction of the component, in the above scheme, you have to make a minimal change on the public method to reflect the param structure. Something like.
[tt]
<public>
<method name="SendNote">
<parameter name="ParamDict" internalName="odic" />
</method>
</public>
[/tt]
Or make some more appealing names. (Another scheme is to make read-write (public <get /><put /> properties to mirror From, To etc and use the .property format to write to the instance. But, it seems to involve more change.---Just a thought.)

- tsuji
 
-Further Notes II-

My last note on the <parameter...> may be mal-conceived. I would take it back pending further study or op's feedback.

- tsuji
 
Upon re-exam the structure of the wsc, I do not see anything wrong with the scheme proposed on modifying <parameter> tag. It should work. Try it out?

- tsuji
 
LOL, that's too funny tsuji. Any more thoughts? :)

Thank you for your input! The dictionary object is a useful tool that I should get in the habit of using. The only thing I don't like about that solution is that I'm basically trying to create an alternative to a true dll. See, I don't have the privelege to have .net or anything of that sort on my machine, so I'm limited to script. If I use a dictionary object, then when I create a type library for my component and view the properties via object browser of VB (in excel or other), I will only see the dictionary object and not each parameter that I'm supposed to pass. Not a big deal for me as the programmer, but for other users who are not familiar with the component it would be nice to be self documented. Perhaps I should request .net... yes, that's what I'll do!

I do appreciate your responses! Sorry I'm too picky.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top