tag:blogger.com,1999:blog-248633262024-03-07T22:27:10.858-05:00Don McNallyThoughts on technology, SharePoint, Lotus Notes/Domino, music and whatever else pops into my head.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.comBlogger92125tag:blogger.com,1999:blog-24863326.post-2475201589930256822013-08-02T09:44:00.000-04:002013-08-06T09:21:36.322-04:00A Great Little League Season!For the last four years, I have coached our daughter's softball team. Well, it actually started two years before that in tee ball, but that wasn't "softball". Two years ago, I was a coach for the 7-8 year old team that played in a local district tournament. That taught me a lot about coaching and how to play to win games. Last year, I was a coach for the 9-10 team and I learned even more, though we had a young team and didn't win a game.<br />
<br />
This year was different. Half the team was girls that had played on last year's 9-10 team and most of the others played on last year's 7-8 team that finished second in their tournament. We had experience, and it showed. Our first game in the District tournament was against an opponent (West Portage) who traditionally fields tough teams and the game went back and forth until we finally took the lead in the top of the 6th. We brought in our best pitcher to close the game, and that she did. I even got a little choked up after the game when I told the girls how proud I was of them (and they reminded me of that after every game we played). Our second game was against a league (Parchment) that our league had traditionally had trouble beating but we were able to win 7-0. Our third game was against a team (Gull Lake) that had beaten their other opponents pretty handily and, because they had been winning as well, were able to use their best pitchers. We beat them too!<br />
<br />
That brought us to the championship game against West Portage. They had gotten back to us by winning 4 games in 5 days - in 90+ degree heat. It was #1 pitcher against #1 pitcher, but we had the advantage of being rested. It was close for a while but our girls poured it on as the other team tired and we won 13-2 in 5. It took a minute to realize that we were District 2 Champions! After running around the field with the banner and taking lots of pictures, we got our shirts and our pins and lots of information about playing in the state tournament in Escanaba. Yes, Escanaba - 8 hours away. Some of the families had to make big sacrifices to make it happen, but all 12 girls were able to go for at least part of the tournament. Amazing! We had a couple more practices for fine tuning and focus, and then we were off to the Upper Peninsula. And the adventure part of the story began.<br />
<br />
We ended up being in the UP from Thursday through Tuesday morning. We were scheduled for pool play from Friday through Sunday, followed by a single elimination tournament for the top 8 teams. Thursday night there were tornado warnings so our initial coaches meeting was cut short and there were no games Friday because it rained CONSTANTLY. Like nearly biblical amounts of rain. Every building we went into had buckets somewhere to catch leaks. We played Friday's schedule on Saturday and beat Tecumseh 4-2, which was really exciting. They were a tough team and looked as though they had played together for a while. We got approval to play doubleheaders on Sunday (Saturday and Sunday's scheduled games) so we could get back on schedule but it rained all day Sunday too! Then, so that we could get everyone at least 2 games and make it a legitimate tournament without keeping everyone there for 10 days, the coaches agreed to change to a 16-team single elimination bracket seeded by the results of Saturday's games.<br />
<br />
We played a team (Clare) who didn't have their #1 pitcher on Saturday because she was sick so they were seeded lower than they probably should have been. We got down by 5 in the first and took a while for our bats to wake up. We almost came back in the 6th but lost 7-5. It was a good game where each team got nice hits and made good defensive plays. We had stayed at the same hotel as Clare and some of the girls had gotten to know each other a little bit so that made it fun. Plus, they were just nice people.<br />
<br />
We had a lot of "down time" because of the rain but got to do some fun things together and a little bit of sightseeing up there. We all went bowling Friday night and almost everyone went out to Rapid River Falls (it was really more of a "rapids" than a "falls") on Monday morning. We practiced in a nice park in the drizzle, had a couple of "team dinners", including a final one in the park where we had practiced, and spent a lot of time in the hotel pool. We said goodbye to one team member who had to go home early and made arrangements so two others could stay when their families needed to go home. We took care of each other.<br />
<br />
I'm proud that we are (I think) the first Westwood 9-10 softball team to win the District. I'm also proud that we were the only Westwood team to win the District this year. These girls represented Westwood so well! If we had played the original schedule, we'd have gotten at least 3 games (and probably 4, based on our pool). But we were 4-0 in the district and 1-1 in the state and can always say we're District Champions - we have the banner to prove it. :) And it was a fun ride overall. I hope this wasn't a "once in a lifetime experience", but if it was, it was worth every minute.<br />
<br />
<a href="http://technorati.com/tag/show-n-tell%20thursday" rel="tag"></a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-51763038541520647052013-05-18T20:22:00.000-04:002013-05-18T20:22:47.326-04:00Building a Softball Bat Rack from PVC PipeOur dugouts have been quite cluttered this year with bats hanging through the chain link fence and falling to the ground, or just laying on the ground in the first place. I've seen bat holders made from PVC in other places but couldn't find a pattern or instructions to create one so I just figured it out on my own. I thought I'd document it here so I could refer back to it and so others might be able to benefit.<br />
<br /><a href="http://technorati.com/tag/show-n-tell%20thursday" rel="tag"></a>
I used 3" diameter PVC for my holder. I had 1.5" at home but that seemed too small. When I looked at it at the store, the 2" seemed too small also, but I think it might have worked. Anyway, I cut a 30" length and was able to put slots for nine bats in it. This is the pattern I created for each slot.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-To_7GI6sLcy8v7Q9m0JCuk4HuHs1kzH2_ZtoZZisMMERztvSLA-rfBZxKvu0lxT48rLvBCnM6MyaIpz66UzRiZLb5QfehPlh8vYwXxYnsq-iSwwAsPLMQdb5EIKQziq3FMhCpA/s1600/img006.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-To_7GI6sLcy8v7Q9m0JCuk4HuHs1kzH2_ZtoZZisMMERztvSLA-rfBZxKvu0lxT48rLvBCnM6MyaIpz66UzRiZLb5QfehPlh8vYwXxYnsq-iSwwAsPLMQdb5EIKQziq3FMhCpA/s320/img006.jpg" width="188" /></a></div>
It should be about 4.25" tall when printed. I found it worked best for tracing on the pipe when I printed it on card stock. Cut along the outside edge of the black line and it will be about the right size. I used a scrolling saw to cut each slot. Getting it started was the hardest part but it only took me a couple of tries to get a good feel for how to do it. And only one bent blade! :)<br />
<br />
I left about 1" between the top parts (the wider part, for the knob of the bat) of each slot, and I cut one before I traced the next one in case my cut got a little away from me. Make sure you line up the tops and bottoms of the slots so the bats all hang the same.<br />
<br />
To attach them to the chain link fence, I used a hose clamp that fit up to a 4" pipe and put the clamp in between slots. Maybe I'll add a picture of that later. Hang it so that the bottoms of the slots are along the bottom of the pipe so that the bats hang straight down.<br />
<br />
It took about 90 minutes and about $15 to make two of these. I just put them up today and our first game isn't until Tuesday. I think the girls - and the others who use those fields - will be pleasantly surprised!Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-68863531832635519382013-03-15T16:10:00.000-04:002013-03-15T16:10:19.119-04:00XPages: Returning to the Prior PageI read <a href="http://xcellerant.net/2013/03/15/return-to-last-view/" target="_blank">this post</a> from Brad Balassaitis and shared that "I should have blogged that last year when I did it". A couple of people encouraged me to blog it just for a different perspective, so here we go.<br />
<br />
I have a button in my left navigator that opens an XPage for processing documents with a bar code scanner. That XPage does not include the navigator; it's like a new document. Once the user is done processing, they click a Finished button and I wanted them to go back where they came from.<br />
<br />
My method of saving the page is the same as Brad's: a sessionScope variable. This is the code in an Execute Script action in the button before it opens the new page:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">var curURL = context.getUrl().toString(); </span><br />
<span style="font-family: "Courier New", Courier, monospace;">sessionScope.put("bundleProcReturn",@RightBack(curURL,"/"));</span></blockquote>
As I look at it, perhaps view.getPageName() would be more efficient, but I didn't know about it at the time and I can't argue with success. :)<br />
<br />
In the Finished button, the Open Page action computes the Page Name value as:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New", Courier, monospace;">sessionScope.get("bundleProcReturn"); </span></blockquote>
It's really handy that so many things in XPages can be computed. Once you understand that, you can use that feature to have your applications do exactly what you want. It takes a little more time to keep track of things like the page you were on when you launched an action, but the user experience can be so much better - and easier for users transitioning from a Notes client app to the XPages version of the app.<br />
<br />
That isn't to say I want to make my XPages apps look and behave like a Notes client app, but there are times when those behaviors are "expected" or "normal".Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com2tag:blogger.com,1999:blog-24863326.post-60167648518065456272013-02-02T21:16:00.000-05:002013-02-02T21:16:06.718-05:00XPages: Detecting and Logging Field Value ChangesRecently I had a request to add functionality to an XPages application I wrote and implemented last year. They wanted the ability to log changes made in specific fields. I did some searching and found the resources I needed:<br />
<br />
<a href="http://openntf.org/XSnippets.nsf/snippet.xsp?id=server-side-value-change-events-listeners" target="_blank">valueChangeListener code as a managed bean</a> by Tony McGuckin, which was linked from <br />
<a href="http://www.qtzar.com/blog/using-a-valuechangelistener-to-build-an-audit-trail/" target="_blank">valueChangeListener implementation code</a> from Declan Sciolla-Lynch, which pointed to<br />
A <a href="http://www.dominoguru.com/pages/xpages_ssjs_multivalue_append_prepend_values.html" target="_blank">better way to update log fields</a> by Chris Toohey<br />
<br />
I used my "R&D skills" to set up the code in my application and was excited when it seemed to work right off the bat. I moved it to the QA environment and then things started going bad. I kept getting Null Pointer Exception errors when I tried to add and update documents. I eventually realized a) I hadn't tried to create documents on the development server, and b) I hadn't tried to update documents that had never been updated previously. Neither the valueChangeListener bean nor the addToList function were working if the starting value of the field was an empty string.<br />
<br />
I still need to figure out how to identify an empty string in those fields to properly handle that situation, but I got around it by making a few changes in the code and by adding a default value to a field so it doesn't start as blank.<br />
<br />
The "do something useful" code to put in Tony's bean ('c' is a UIComponent object):<br />
<blockquote class="tr_bq">
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">// Get the name of the field that changed</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">String changedExpression = c.getValueBinding("value").getExpressionString(); </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">int firstDot = changedExpression.indexOf(".") + 1; </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">int closingBracket = changedExpression.indexOf("}"); </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">String changedField = changedExpression.substring(firstDot,closingBracket); </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">// Get the old and new values in the field</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">String oldValue;</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">try {</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> oldValue = valueChangeEvent.getOldValue().toString(); </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">} catch (NullPointerException npex) {</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> oldValue = "";</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">} catch (Exception ex) {</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> System.out.println("Major failure");</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> ex.printStackTrace();</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> oldValue = "";</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">};</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">String newValue = valueChangeEvent.getNewValue().toString(); </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">Map<string bject=""> viewScope = ExtLibUtil.getViewScope(); <br />HashMap<string bject=""> oldValuesMap = new HashMap<string bject="">(); <br />HashMap<string bject=""> newValuesMap = new HashMap<string bject="">(); <br /> <br />if (viewScope.containsKey("oldValues")){ <br /> oldValuesMap = (HashMap<string object="">) viewScope.get("oldValues"); <br /> newValuesMap = (HashMap<string object="">) viewScope.get("newValues"); <br />} <br /> <br />oldValuesMap.put(changedField, oldValue); <br />newValuesMap.put(changedField, newValue); <br /> <br />viewScope.put("oldValues", oldValuesMap); <br />viewScope.put("newValues", newValuesMap);</string></string></string></string></string></string></string></span></span></blockquote>
Code to read the old and new values and write them to a log field named ActivityHistory:<br />
<blockquote class="tr_bq">
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">var dNow = @Now();</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">if (viewScope.containsKey("oldValues")){</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> var oldValues:java.util.HashMap = viewScope.get("oldValues");</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> var newValues:java.util.HashMap = viewScope.get("newValues");</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> for (key in oldValues.keySet()) {</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> actText = "Field " + key + " changed from '" + oldValues.get(key) + "' to '" + newValues.get(key) + "' - " + @Name("[CN]",session.getEffectiveUserName()) + " on " + @Text(dNow);;</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> addToList(bundleDoc,"ActivityHistory",actText,"last");</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">}</span></span> </blockquote>
Updated addToList code (I used 'first' and 'last' instead of 'prepend' and 'append'):<br />
<blockquote class="tr_bq">
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">function addToList(datadoc:NotesXspDocument, fieldname:string, newVal:string, addPos:string) {</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> var newArr = new Array(datadoc.getItemValue(fieldname));</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> switch (addPos) {</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> case 'first':</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> newArr.unshift(newVal);</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> break</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> case 'last':</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> newArr.push(newVal);</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> break</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> }</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> datadoc.replaceItemValue(fieldname,newArr);</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> return true;</span></span><br />
<span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">}; </span></span></blockquote>
<br />
If anyone can explain what I missed with fields that start with a value of empty string, I'd appreciate it as I'm very early in my XPages and Java learning. In the mean time, I hope this proves useful to others.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-4603522374865725072013-01-31T21:43:00.000-05:002013-01-31T21:43:13.785-05:00New DesignJust a quick, rather meaningless post, to say that I changed to a new design on the site. I thought it was time to update to something with a more "current" design. Let me know if you run into any issues using it.<a href="http://technorati.com/tag/show-n-tell%20thursday" rel="tag"></a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-29922249861147433342012-01-24T15:26:00.002-05:002012-01-24T15:56:29.043-05:00More Excel Code: Inserting and Copying RowsI was working on some code to export data to a pre-formatted Excel file and, as part of that, needed to be able to insert rows into a range so that the data I added would be included in formulas below it (they were column totals and data summaries). As I find typical when trying to control Excel from LotusScript, I couldn't locate examples of the code I needed. That doesn't mean they aren't out there, just that I couldn't find them.<br /><br />After some experimentation and some dumb luck stumbling on information that referred to methods I wasn't aware of in the COM interface, I came up with the code below.<br /><br /><pre><div style="FONT-FAMILY: sans-serif; COLOR: black; FONT-SIZE: 9pt"><span style="COLOR: blue">Sub</span> CopyFormulas<span style="COLOR: blue">(</span>xlSheet <span style="COLOR: blue">As</span> <span style="COLOR: blue">Variant</span><span style="COLOR: blue">,</span> rowNum <span style="COLOR: blue">As</span> <span style="COLOR: blue">Integer</span><span style="COLOR: blue">,</span> firstCol <span style="COLOR: blue">As</span> <span style="COLOR: blue">Integer</span><span style="COLOR: blue">,</span> lastCol <span style="COLOR: blue">As</span> <span style="COLOR: blue">Integer</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">Dim</span> x <span style="COLOR: blue">As</span> <span style="COLOR: blue">Integer</span><br /> <span style="COLOR: blue">Dim</span> cellVal <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><br /> xlSheet<span style="COLOR: blue">.</span>Activate<br /> xlSheet<span style="COLOR: blue">.</span>Cells<span style="COLOR: blue">(</span>rowNum<span style="COLOR: blue">-</span>1<span style="COLOR: blue">,</span>1<span style="COLOR: blue">)</span><span style="COLOR: blue">.</span>EntireRow<span style="COLOR: blue">.</span>Copy<br /> xlSheet<span style="COLOR: blue">.</span>Cells<span style="COLOR: blue">(</span>rowNum<span style="COLOR: blue">,</span>1<span style="COLOR: blue">)</span><span style="COLOR: blue">.</span>EntireRow<span style="COLOR: blue">.</span>Select<br /> xlSheet<span style="COLOR: blue">.</span>PasteSpecial<span style="COLOR: blue">(</span>7<span style="COLOR: blue">)</span><br /> xlSheet<span style="COLOR: blue">.</span>Application<span style="COLOR: blue">.</span>CutCopyMode <span style="COLOR: blue">=</span> <span style="COLOR: purple">False</span><br /> <span style="COLOR: blue">For</span> x <span style="COLOR: blue">=</span> firstCol <span style="COLOR: blue">To</span> lastCol<br /> cellVal <span style="COLOR: blue">=</span> xlSheet<span style="COLOR: blue">.</span>Cells<span style="COLOR: blue">(</span>rowNum<span style="COLOR: blue">,</span>x<span style="COLOR: blue">)</span><span style="COLOR: blue">.</span>Formula<br /> <span style="COLOR: blue">If</span> <span style="COLOR: blue">Left</span><span style="COLOR: blue">(</span>cellVal<span style="COLOR: blue">,</span>1<span style="COLOR: blue">)</span> <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">"="</span> <span style="COLOR: blue">Then</span><br /> xlSheet<span style="COLOR: blue">.</span>Cells<span style="COLOR: blue">(</span>rowNum<span style="COLOR: blue">,</span>x<span style="COLOR: blue">)</span><span style="COLOR: blue">.</span>ClearContents<br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">Next</span><br /><span style="COLOR: blue">End</span> <span style="COLOR: blue">Sub</span></div></pre><br /><br /><div style="MARGIN: 5px 50px; FONT-FAMILY: sans-serif; COLOR: gray; FONT-SIZE: 8pt"><br /><center>This LotusScript was converted to HTML using the <b><i>ls2html</i></b> routine,<br />provided by Julian Robichaux at <a href="http://www.nsftools.com" target="_blank">nsftools.com</a>.</center></div><br /><br />This takes the Worksheet object you pass it, copies the content and format of the row above your current row into your current row and then removes the contents of a defined set of columns if they are not formulas. The problems I had were that the copy was not done in the proper place and I wasn't maintaining the formulas and formatting of the row I was copying.<br /><br />The copy location was solved by adding the xlSheet.Activate line. My code was writing data to three different worksheets (one each for month-to-date, quarter-to-date and year-to-date) so I found that adding that line made sure the proper sheet was active.<br /><br />The formatting issue was resolved by a combination of two methods. One is .PasteSpecial(7) , where the 7 represents the xlPasteAllExceptBorders paste option. The other is the .ClearContents method. I was using the .Paste and .Clear methods initially. I suspect I could use the .Paste and .ClearContents methods, since I think the .Clear method was the culprit that was deleting the formats, but I am going to leave it the way it is since a) I know it works, and b) the .PasteSpecial method indicates what I am really trying to do.<br /><br />By the way, the code to insert a row is xlSheet.Cells(row,col).EntireRow.Insert.<br /><br />Enjoy! Now, how many times do you think I'll find this blog post when I search for this in the future? :)Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-26798609058037027912011-06-28T12:38:00.004-04:002011-06-28T12:49:22.128-04:00Inheriting Field Values for Names FieldsI had a problem last week with a couple of forms that have fields that inherit values from fields on the document that is open when the new document is created. On one form, the field values were set properly, but on the other they were not. The form being created is a response-to-response form. The form that worked was a response form, so at first I thought the problem with the form that was not working was because it was a main form. I discovered that wasn't the problem when I was able to get that form to inherit a text field.<br /><br />The fields I was trying to inherit were names fields. And the two "parent" forms used different names for the names I wanted to inherit. On the form that worked, the fields were named the same on that form and on the child form I was using for my new document. Aha! I changed the field name on the child form to match that of the form that didn't work, and that started working; of course, that also broke the other form that worked previously.<br /><br />What I ended up doing was adding a Computed For Display field to the child form that was named the same as the field on the form that didn't work. It has a value in it when a new child is created and is blank at all other times. I then reference that field in the formula for my name field and it works for both forms.<br /><br />I couldn't find anything that said Names fields inherit differently than other fields. but they apparently are different. After spending about 4 hours trying to figure it out, I figured I'd write it out here, just in case it comes up again.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-17435090102779957562011-03-31T15:45:00.005-04:002011-03-31T16:00:24.255-04:00Barcodes in Lotus Notes Applications<p><img src="http://webpages.charter.net/dtmc/images/SNTTbtn.png" align="right" />If you have ever wanted to implement barcoding in a Notes application, it may be easier to do so than you think. You really need four things to make it work: </p><br /><ol><br /><li>A barcode font that is deployed to machines that will be printing the things (eg. paper or labels) that have the barcode on them. </li><br /><li>LotusScript code to generate the field value for the barcode. Simple barcodes, like Code 39, just need start and stop characters before and after the number you are putting on a barcode, but they have a limited character set. More complex barcodes, like Code 128, require start and stop characters as well as check digits but are able to include the alphanumeric character set. </li><br /><li>A barcode scanner. </li><br /><li>An input form to handle the scanner’s output and cause processing to happen. </li></ol><br /><p>Though the application I am working on is encoding a 12-digit number, we are deploying a Code 128 font so that we will be ready if we expand the use of barcodes into an application that requires alphabetic characters as well. Scanner set up is pretty easy now, with most being able to plug and play with your computer hardware and able to be configured by scanning barcodes. They function similarly to keyboards, in that if you are some sort of input area (eg. a field or even the body of a mail message), the scanner will feed the data from the barcode into the field as though you typed it on a keyboard. </p><br /><p>The vendor we used for the font also supplies code for many different applications, including LotusScript. However, to get the number I encoded to print as part of the barcode, I had to take their VBA script and modify it for LotusScript because their LotusScript code does not support human-readable codes. It was a pretty simple code change though. I configured the scanner to append a tab to each scan that it completed (explanation of why is below). I just plugged it in and then scanned seven codes on a sheet that came with the scanner and it was ready to go. </p><br /><p><strong>The Application</strong></p><br /><p>The processing form is displayed as a dialog box that allows the user to set some processing options before the input field is displayed. This is done with a programmable table with the options on one tab and the processing actions on a second tab, with buttons to toggle between the two tabs. This helps to ensure the cursor is in the input field when ready to scan by making it the only editable field visible. </p><br /><p><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNSPA0aVji5fC7anW_X0IJIoUMUVpqdyHRO1TS_SK5mae5XmSWnJZSOVvMg-R8ne-oREMda-UEYb7yCD1fmPuku9Pqb1y9_LZrx6m6ek61Kt3hyYx8NGA7JwEdFQL15i1nY8_TxA/s1600/barcode-designer.JPG"><img id="BLOGGER_PHOTO_ID_5590333855596358626" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 268px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNSPA0aVji5fC7anW_X0IJIoUMUVpqdyHRO1TS_SK5mae5XmSWnJZSOVvMg-R8ne-oREMda-UEYb7yCD1fmPuku9Pqb1y9_LZrx6m6ek61Kt3hyYx8NGA7JwEdFQL15i1nY8_TxA/s320/barcode-designer.JPG" border="0" /></a> The form has the main input field (TrackingNum) and a second, unmarked input field (ActionField) on it. By unmarked, I mean that it is a simple text field that has the Show Field Delimiters option unchecked. The scanner sends the decoded data from the barcode plus a tab character. The tab moves the cursor from the TrackingNum field to the ActionField field. The processing code is in the OnBlur event of the TrackingNum field; that code takes the number from the barcode, finds the document and updates it as necessary. The ActionField field has code in the OnFocus event to move the cursor back to the TrackingNum field, which makes the dialog ready for the next scan. </p><br /><p>The form needed to be functional manually as well as with the scanner so the TrackingNum field is defined as a combobox and the form has a button on it that, when clicked, moves the cursor out of the TrackingNum field. The combobox lists items that are available for the user to process and can also be used to type in any number manually. The button just puts the cursor into the ActionField field, which then moves the cursor back to the TrackingNum field. </p><br /><p>This is what the dialog looks like. Processing Messages is a reverse-chronological list of the actions taken each time an entry in the TrackingNum field is processed. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTovHhnyooGjQOYcS0hqraJROLUofPTs1pfEbais_ORFUmoltVCV5OLXgwJzkKL70T1ipuRMzshM7sxU9hs7vNewYagb4JxAGwdvCH2ed3dFLiCz4K3PEIaxs-q20F65M_tEtWQ/s1600/barcode-client.JPG"><img id="BLOGGER_PHOTO_ID_5590334116114696386" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 320px; CURSOR: hand; HEIGHT: 226px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQTovHhnyooGjQOYcS0hqraJROLUofPTs1pfEbais_ORFUmoltVCV5OLXgwJzkKL70T1ipuRMzshM7sxU9hs7vNewYagb4JxAGwdvCH2ed3dFLiCz4K3PEIaxs-q20F65M_tEtWQ/s320/barcode-client.JPG" border="0" /></a> I couldn’t find a lot about barcoding in Notes, and found nothing about how to actually code an application to interact with a scanner, but I did receive a hints from a couple of Lotus peeps that really helped. In the end, it was a lot easier than I expected. </p><br /><p>Technorati: <a href="http://technorati.com/tag/show-n-tell" rel="tag">Show-n-Tell Thursday</a> </p>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com2tag:blogger.com,1999:blog-24863326.post-81259858135318607712011-01-27T13:37:00.002-05:002011-01-27T13:59:42.656-05:00Get Database Information for Configuration Documents<img src="http://webpages.charter.net/dtmc/images/SNTTbtn.png" align="right" />I've done a lot of work lately to make our applications more configurable. Most of it is related to having separate servers for development, QA and production, and needing to be able to change reference databases without requiring code changes at each stop in the change control process.<br /><br />As part of that, I wanted to make it easier to enter the information we required for the reference databases. Sure, you could find the database and then type in the server name and path name (or replica ID), but we had so many that it became a burden to do it that way.<br /><br />So I created the script below. This could be a function in a script library or could be added in the form globals.<br /><br /><pre><div style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: sans-serif"><br /><span style="COLOR: blue">Sub</span> SetDatabaseInfo<span style="COLOR: blue">(</span>actionID <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><span style="COLOR: blue">,</span> docObj <span style="COLOR: blue">As</span> <span style="COLOR: blue">Variant</span><span style="COLOR: blue">,</span> titleField <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><span style="COLOR: blue">,</span> serverField <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><span style="COLOR: blue">,</span> pathField <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><span style="COLOR: blue">,</span> repIDField <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><span style="COLOR: blue">)</span><br /><span style="COLOR: green">%REM<br /> This function allows the user to select a database and set up to four fields with information from the selected database:<br />(0) Database Title<br />(1) Server<br />(2) File path<br />(3) Replica ID<br /><br />Parameters are:<br /> actionID = 'Set' to set the field values, 'Clear' to clear the field values<br /> docObj = the document to be modified. Can be a NotesDocument or NotesUIDocument<br /> titleField = item name for the database title<br /> serverField = item name for the database server name<br /> pathField = item name for the database path<br /> repIDField = item name for the database replica ID<br /><br />If Cancel is chosen in the dialog, the document passed in is not changed.<br />The user receives an error if the file they chose cannot be opened.<br />%END REM</span><br /> <br /> <span style="COLOR: blue">Dim</span> ws <span style="COLOR: blue">As</span> <span style="COLOR: blue">New</span> <span style="COLOR: black">NotesUIWorkspace</span><br /> <span style="COLOR: blue">Dim</span> nname <span style="COLOR: blue">As</span> <span style="COLOR: black">NotesName</span><br /> <span style="COLOR: blue">Dim</span> session <span style="COLOR: blue">As</span> <span style="COLOR: blue">New</span> <span style="COLOR: black">NotesSession</span><br /> <span style="COLOR: blue">Dim</span> db <span style="COLOR: blue">As</span> <span style="COLOR: black">NotesDatabase</span><br /> <span style="COLOR: blue">Dim</span> notesDataPath <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><br /> <span style="COLOR: blue">Dim</span> filePath <span style="COLOR: blue">As</span> <span style="COLOR: blue">Variant</span><br /> <span style="COLOR: blue">Dim</span> result <span style="COLOR: blue">As</span> <span style="COLOR: blue">Variant</span><br /> <span style="COLOR: blue">Const</span> PROMPT_CHOOSEDATABASE <span style="COLOR: blue">=</span> 13<br /> <span style="COLOR: blue">Dim</span> fileInfo<span style="COLOR: blue">(</span>3<span style="COLOR: blue">)</span> <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><br /> <span style="COLOR: blue">Dim</span> docObjType <span style="COLOR: blue">As</span> <span style="COLOR: blue">String</span><br /> <br /> docObjType <span style="COLOR: blue">=</span> <span style="COLOR: blue">Typename</span><span style="COLOR: blue">(</span>docObj<span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">If</span> docObjType <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">"NOTESDOCUMENT"</span> <span style="COLOR: blue">And</span> docObjType <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">"NOTESUIDOCUMENT"</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Exit</span> <span style="COLOR: blue">Sub</span><br /> <br /> <span style="COLOR: blue">Select</span> <span style="COLOR: blue">Case</span> <span style="COLOR: blue">Ucase</span><span style="COLOR: blue">(</span>actionID<span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">Case</span> <span style="COLOR: black">"SET"</span><br /> notesDataPath <span style="COLOR: blue">=</span> <span style="COLOR: blue">Ucase</span><span style="COLOR: blue">(</span>session<span style="COLOR: blue">.</span>GetEnvironmentString<span style="COLOR: blue">(</span><span style="COLOR: black">"Directory"</span><span style="COLOR: blue">,</span><span style="COLOR: purple">True</span><span style="COLOR: blue">)</span><span style="COLOR: blue">)</span> <span style="COLOR: blue">&</span> <span style="COLOR: black">"\"</span><br /> result <span style="COLOR: blue">=</span> ws<span style="COLOR: blue">.</span>Prompt<span style="COLOR: blue">(</span>PROMPT_CHOOSEDATABASE<span style="COLOR: blue">,</span><span style="COLOR: black">"Choose Database"</span><span style="COLOR: blue">,</span><span style="COLOR: black">"Choose the database for which you want information:"</span><span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">If</span> <span style="COLOR: blue">Isempty</span><span style="COLOR: blue">(</span>result<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">Exit</span> <span style="COLOR: blue">Sub</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <br /> <span style="COLOR: blue">Set</span> db <span style="COLOR: blue">=</span> <span style="COLOR: blue">New</span> <span style="COLOR: black">NotesDatabase</span><span style="COLOR: blue">(</span><span style="COLOR: black">""</span><span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">If</span> <span style="COLOR: blue">Not</span> db<span style="COLOR: blue">.</span><span style="COLOR: blue">Open</span><span style="COLOR: blue">(</span>result<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span><span style="COLOR: blue">,</span>result<span style="COLOR: blue">(</span>1<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">Messagebox</span> <span style="COLOR: black">"Error opening database; you may not have access to it"</span><span style="COLOR: blue">,</span>48<span style="COLOR: blue">,</span><span style="COLOR: black">"Error"</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> filePath <span style="COLOR: blue">=</span> <span style="COLOR: blue">Ucase</span><span style="COLOR: blue">(</span>db<span style="COLOR: blue">.</span>FilePath<span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">If</span> result<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span> <span style="COLOR: blue">=</span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> filePath <span style="COLOR: blue">=</span> <span style="COLOR: blue">Strright</span><span style="COLOR: blue">(</span>filePath<span style="COLOR: blue">,</span>notesDataPath<span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> fileInfo<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span> <span style="COLOR: blue">=</span> db<span style="COLOR: blue">.</span>Title<br /> fileInfo<span style="COLOR: blue">(</span>1<span style="COLOR: blue">)</span> <span style="COLOR: blue">=</span> result<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span><br /> fileInfo<span style="COLOR: blue">(</span>2<span style="COLOR: blue">)</span> <span style="COLOR: blue">=</span> filePath<br /> fileInfo<span style="COLOR: blue">(</span>3<span style="COLOR: blue">)</span> <span style="COLOR: blue">=</span> db<span style="COLOR: blue">.</span>ReplicaID<br /> <br /> <span style="COLOR: blue">If</span> fileInfo<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span> <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObjType <span style="COLOR: blue">=</span> <span style="COLOR: black">"NOTESDOCUMENT"</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> titleField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">,</span>fileInfo<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> pathField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">,</span>fileInfo<span style="COLOR: blue">(</span>2<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> repIDField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">,</span>fileInfo<span style="COLOR: blue">(</span>3<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> serverField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">Set</span> nname <span style="COLOR: blue">=</span> <span style="COLOR: blue">New</span> <span style="COLOR: black">NotesName</span><span style="COLOR: blue">(</span>fileinfo<span style="COLOR: blue">(</span>1<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">,</span>nname<span style="COLOR: blue">.</span>Abbreviated<span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span> <br /> <span style="COLOR: blue">Elseif</span> docObjType <span style="COLOR: blue">=</span> <span style="COLOR: black">"NOTESUIDOCUMENT"</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> titleField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">,</span>fileInfo<span style="COLOR: blue">(</span>0<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> pathField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">,</span>fileInfo<span style="COLOR: blue">(</span>2<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> repIDField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">,</span>fileInfo<span style="COLOR: blue">(</span>3<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> serverField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">Set</span> nname <span style="COLOR: blue">=</span> <span style="COLOR: blue">New</span> <span style="COLOR: black">NotesName</span><span style="COLOR: blue">(</span>fileinfo<span style="COLOR: blue">(</span>1<span style="COLOR: blue">)</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">,</span>nname<span style="COLOR: blue">.</span>Abbreviated<span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <br /> <span style="COLOR: blue">Case</span> <span style="COLOR: black">"CLEAR"</span><br /> <span style="COLOR: blue">If</span> docObjType <span style="COLOR: blue">=</span> <span style="COLOR: black">"NOTESDOCUMENT"</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> titleField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> pathField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> repIDField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> serverField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>ReplaceItemValue<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span> <br /> <span style="COLOR: blue">Elseif</span> docObjType <span style="COLOR: blue">=</span> <span style="COLOR: black">"NOTESUIDOCUMENT"</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> titleField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>titleField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> pathField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>pathField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> repIDField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>repIDField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">If</span> serverField <span style="COLOR: blue"><</span><span style="COLOR: blue">></span> <span style="COLOR: black">""</span> <span style="COLOR: blue">Then</span><br /> <span style="COLOR: blue">If</span> docObj<span style="COLOR: blue">.</span>Document<span style="COLOR: blue">.</span>HasItem<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">)</span> <span style="COLOR: blue">Then</span> <span style="COLOR: blue">Call</span> docObj<span style="COLOR: blue">.</span>FieldSetText<span style="COLOR: blue">(</span>serverField<span style="COLOR: blue">,</span><span style="COLOR: black">""</span><span style="COLOR: blue">)</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">If</span><br /> <br /> <span style="COLOR: blue">End</span> <span style="COLOR: blue">Select</span><br /><span style="COLOR: blue">End</span> <span style="COLOR: blue">Sub</span><br /></div></pre><br /><br /><div style="BORDER-RIGHT: 1px solid; BORDER-TOP: 1px solid; FONT-SIZE: 8pt; MARGIN: 5px 50px; BORDER-LEFT: 1px solid; COLOR: gray; BORDER-BOTTOM: 1px solid; FONT-FAMILY: sans-serif"><center>This LotusScript was converted to HTML using the <b><i>ls2html</i></b> routine,<br />provided by Julian Robichaux at <a href="http://www.nsftools.com/" target="_blank">nsftools.com</a>.</center></div><br /><br />The comments at the top of the code explain pretty well what is going on: pass it the action you want to take, the field names you want to update and the object containing those fields and it does the work. I honestly don't remember why I wrote it to be able to update either a NotesUIDocument or a NotesDocument, since I think I always pass it a NotesUIDocument, but it gives you the flexibility to pass either object type.<br /><br />Technorati: <a href="http://technorati.com/tag/show-n-tell" rel="tag">Show-n-Tell Thursday</a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-90210563126713819722011-01-20T13:11:00.009-05:002022-11-19T11:38:48.406-05:00Configurable Embedded Views (Single Category Views in External Notes Databases)<img align="right" src="http://webpages.charter.net/dtmc/images/SNTTbtn.png" />Have you ever had Notes application A that had related data in Notes application B where you wanted to show the application B data when you opened a document in application A? I have, and I found there are lots of ways to combine data like this. If it were all in one database, it would be pretty trivial to create an embedded view and show the single category that relates to the open document. It gets complicated when you want to leave the data in its source database rather than copying it to where you want it, and feels almost impossible if you then introduce multiple environments (eg. development, QA and production).<br />
<br />
Composite Applications, introduced in Notes 8, were one way to accomplish this, but they never really caught on, due in part to their own deployment issues. XPages is the latest silver bullet that can be used to slay this beast. But what if you don’t have Notes 8.5.1 and aren’t going to move to it in the near future? Or you don’t have the time to focus on learning XPages right now?<br />
<br />
There is a way to make these related applications work in a configurable way in the Notes 6 and 7 client. This is not original thinking. See Nathan Freeman’s blog (ntf.gbs.com) for the Sesame Street and Area 51 demos for the earlier documentation. I just thought it was worth bringing up again.<br />
<br />
The entire solution is based on three features of Domino Designer and Notes that haven’t gotten a lot of attention: computable frameset contents, embedded editors and forms that open in framesets. Nathan’s Sesame Street demo showed how you could embed a fully functional frameset on a form. That was great, unless you only wanted a single category of a view. That problem was solved in the Area 51 demo.<br />
<br />
For this demo, I have an application catalog. Not *the* application catalog that each Domino server has, but one that adds on to that catalog to add a description, an application owner and technical support staff. Rather than copying everything from the system catalog, we’ll reference the catalog from within our application. I’ll refer to the application catalog as the “source” database and the system catalog as the “target” database. The source database documents will contain the replica ID of the application database that will be our lookup key for the target database.<br />
<ol></ol>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhypfBUB5KBxNpMn9kk-MIQdTkSPJBhyZ5gScKLmS7m3px__168zo8_tgU-cZhqql9liH-I_LkKYdDnbEWC3lEfwpd5VTtpLWaeVvF_sdi9-XQnwDJoeDvUerKldCHsD58hYg_WEA/s1600/AppTab1.JPG"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5564338063931007010" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhypfBUB5KBxNpMn9kk-MIQdTkSPJBhyZ5gScKLmS7m3px__168zo8_tgU-cZhqql9liH-I_LkKYdDnbEWC3lEfwpd5VTtpLWaeVvF_sdi9-XQnwDJoeDvUerKldCHsD58hYg_WEA/s320/AppTab1.JPG" style="cursor: hand; display: block; height: 158px; margin: 0px auto 10px; text-align: center; width: 320px;" /></a><br />
<br />
<b>Target Database</b><br />
1. Create a form in the system catalog with an embedded view on it, with the view being one categorized by replica ID. You can create a view specific to your needs or use one that is already in the system catalog.<br />
<br />
2. Set the form so that it does not appear on the Create menu.<br />
<br />
3. On the embedded view, the Show Single Category property should be set to @Word(@Environment(“Catalog_Ref”);”~” ;4). The environment variable will be set by the source application and will be explained in the next section.<br />
<br />
4. Save the form with the name OneReplica.<br />
<br />
This must be created in the target database so that you can choose the “Current Database” option as the source of the embedded view. Because there is not a way to programmatically select the source of an embedded view, this ensures the proper view will always open, whether you are looking at your Dev, QA or Production system catalog.<br />
<br />
<b>Source Database</b><br />
This database should already have a form in it for the application items that you want in addition to what is in the system catalog. To make this work, you need a field on the form for the replica ID of the application, and the value should be in the formula format (12345678:87654321), unless you created a new view in the target database that reformats the replica ID. You should also have a view that lists the application documents.<br />
<br />
There are two elements that need to be added in the source database and one change to the application form you already have. The new elements are a frameset that will display the form from the target database, and a wrapper form that is set to display in a frame of the new frameset. On the application form, you need to add an embedded editor that will display the wrapper form.<br />
<br />
1. Create a frameset with three frames: two side-by-side on top and one full width on the bottom. Set the top frames to a relative height of 1 and 50% width. The borders should be set to not be 3D and 2 pixels in width.<br />
<br />
2. Name the top left frame NotesView and set its target to NotesDocView. Set the Content Type to Named Element and click the ‘@’ icon to enter formulas to determine the element. The kind of element should have the formula @Word(@Environment(“Catalog_Ref”);”~” ;2), the database should be the formula @Word(@Environment(“Catalog_Ref”);”~” ;1) and the element name should be the formula @Word(@Environment(“Catalog_Ref”);”~” ;3). The kind and name of the element could actually be constants, but it is a better practice to compute them in case they need to change later or you want to use this frameset for more than one purpose.<br />
<ol></ol>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirTOR7ISwK3V81hGPiehhX8NLzFprMxVdPhc9iBH5rJMMwHghmy9WBYa7ZWj8fX57ZRAeW3M1hV7C_3-KoNkDPRjwVdT-juqD3zt9Of6f-jltGC88pmhKzs7Q4t0mz2IYcLQY1Ow/s1600/ComputedElementDialog.JPG"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5564338842416393682" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirTOR7ISwK3V81hGPiehhX8NLzFprMxVdPhc9iBH5rJMMwHghmy9WBYa7ZWj8fX57ZRAeW3M1hV7C_3-KoNkDPRjwVdT-juqD3zt9Of6f-jltGC88pmhKzs7Q4t0mz2IYcLQY1Ow/s320/ComputedElementDialog.JPG" style="cursor: hand; display: block; height: 280px; margin: 0px auto 10px; text-align: center; width: 320px;" /></a><br />
<br />
3. Name the top right frame NotesDocView.<br />
<br />
4. Name the bottom frame InvisibleMan. The height of InvisibleMan should be 0 pixels, Scrolling should be Off and Allow Resizing should be No. We don’t want to see this frame; it is used only as the target for the form we want to open in a frameset.<br />
<br />
5. Save the frameset as CatalogView.<br />
<br />
6. Create a form. It should be set so that it does not appear on the Create menu. On the Launch properties, set it to open in the CatalogView frameset in the InvisibleMan frame. The only purpose of this form is to open in a frameset so the frameset can appear to be embedded on another form. This form could also set the environment variable, but we are not doing so in this example.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP92y2br6B0MGRTGEPrg6KtFIyG84HZ76Adhg_SDHqha32JVRtuQSzO6QtaeUwSU9EGz82fVln-206ZKvGMssUMcCmpMeda_ChJTmeZsqnZmG-o5qgmtnneL6HgBazPRKPPgW6fQ/s1600/FormProperties.JPG"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5564339160092068370" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP92y2br6B0MGRTGEPrg6KtFIyG84HZ76Adhg_SDHqha32JVRtuQSzO6QtaeUwSU9EGz82fVln-206ZKvGMssUMcCmpMeda_ChJTmeZsqnZmG-o5qgmtnneL6HgBazPRKPPgW6fQ/s320/FormProperties.JPG" style="cursor: hand; display: block; height: 313px; margin: 0px auto 10px; text-align: center; width: 307px;" /></a><br />
<br />
7. Save the form with the name Wrapper.<br />
<br />
8. In the application documentation form (assumed to have been created previously), add an embedded editor that opens the Wrapper form. In the PostOpen of this form, you need code to set the Catalog_Ref environment variable. The variable should be in the format server!!filepath~Form~OneReplica~replicaID. The server could be computed based on the location of the source application and the filepath is probably constant across the environments, so you could probably enter it directly (remember to escape any ‘\’ in the path). The element type and name will be constant and the replica ID is the name of the field containing the replica ID. More likely, the server and filepath for the catalog would be read from a configuration document. Just keep in mind that the location of the target database (that is, both the server and file path) should not be hard coded, because that defeats the purpose of this solution: to make it possible to migrate from your dev to production environment without making programming changes as the moves are completed.<br />
<br />
9. Save the updated form.<br />
<br />
Once everything is saved, go to your source database and open or create a document using the application documentation form. If all goes well, you should see an embedded view that contains the documents from the system catalog for the replica ID of the database you are looking at, and a box to the right that should display the document you click in the view. See, a real embedded frameset!<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPxJKFmMRyrr7AoygVC52weJe4dStFr5MYeI_sunxTNvdFJ_uRD1t3UThbhDojZpjFfOnhnsO-vz1NEt2qql0Om1K-p9IHULhZSBYVJxs4K7Rr4ICHybWR-5eD6JFgDgirgVMF7g/s1600/AppTab2.JPG"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5564340299124366994" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiPxJKFmMRyrr7AoygVC52weJe4dStFr5MYeI_sunxTNvdFJ_uRD1t3UThbhDojZpjFfOnhnsO-vz1NEt2qql0Om1K-p9IHULhZSBYVJxs4K7Rr4ICHybWR-5eD6JFgDgirgVMF7g/s320/AppTab2.JPG" style="cursor: hand; display: block; height: 220px; margin: 0px auto 10px; text-align: center; width: 320px;" /></a><br />
<br />
If you want to prove that it is configurable via the environment variable, set the environment variable to @Implode(@MailDbName;"!!")+"~Folder~($Inbox)" and see that it opens your mail box.<br />
<br />
Once you wrap your head around how this works, the possibilities become nearly endless. Multi-database applications can become far more informative.<br />
<br />
<b>Update:</b> Here is a link to a <a href="https://drive.google.com/file/d/0B9TSgj6TtNu8enR6cDlBQXJLR0E/view?usp=sharing&resourcekey=0-g4lWvHmSvcMe5wxAkn-r6Q" rel="nofollow" target="_blank">complete "Source" database</a> that also includes the form that needs to be copied into the "Target" database. Hope that helps flesh out the example a little more. <br />
<br />
<br />
Technorati: <a href="http://technorati.com/tag/show-n-tell" rel="tag">Show-n-Tell Thursday</a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com18tag:blogger.com,1999:blog-24863326.post-62381538212606540432010-03-27T21:15:00.003-04:002010-03-27T21:18:25.686-04:00Export AOL Address BookI moved my in-laws from AOL to Thunderbird (they just aren't ready to use just web mail) and needed a way to get their address book out of AOL. I did some searching and found a couple of possibilities, but nothing easy and free. I'm pretty sure there isn't an option to export from the AOL client, but I found the way to do it.<br /><br />Use the AOL webmail interface and you can export your address book to an LDIF file. Clean it up if you need to and then import it into Thunderbird. Simple!Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-84832032080137819382009-10-29T14:30:00.003-04:002009-10-29T14:39:12.624-04:00Create Excel Lists Using LotusScript<img src="http://webpages.charter.net/dtmc/images/SNTTbtn.png" align="right" />I have created some code – as many others have over time – to export a Notes view to Excel. The code creates the Excel application object, a workbook and a worksheet and then populates the new worksheet with data from the view. The twist to this request was that once the export was done, they wanted to have some of the columns use the List function of Excel; that is, they wanted to be able to filter the columns based on the values in them.<br /><br />I recorded a macro in Excel to get the VBA code so I could translate it to LotusScript, and this is what I got:<br /> Range("I1").Select<br /> ActiveSheet.ListObjects.Add(xlSrcRange, Range("$I:$I"), , xlYes).Name = "List1"<br /><br />Uh oh. How do I pass parameters to the Add method and set the value for the Name property in the same line? I remembered from past experience, this type of code is tricky to do in LotusScript. Searching didn’t reveal where anyone had done this exact thing before but I found an example that led me to the solution. The code is (I found that xlSrcRange and xlYes both have a value of 1):<br /><style>.lotusscript { font-family: sans-serif; font-size: 9pt; color: black; }<br />.ls-comment { color: green; }<br />.ls-quote { color: black; }<br />.ls-datatype { color: black; }<br />.ls-operator { color: blue; }<br />.ls-keyword { color: blue; }<br />.ls-statement { color: blue; }<br />.ls-function { color: blue; }<br />.ls-class { color: black; }<br />.ls-constant { color: purple; }<br /></style><br /><pre><div class=lotusscript><br /> <font class=ls-statement>Set</font> xlApp <font class=ls-operator>=</font> <font class=ls-function>CreateObject</font><font class=ls-operator>(</font><font class=ls-quote>"Excel.Application"</font><font class=ls-operator>)</font><br /> <font class=ls-statement>Set</font> xlWkBook <font class=ls-operator>=</font> xlApp<font class=ls-operator>.</font>Workbooks<font class=ls-operator>.</font>Add<font class=ls-operator>(</font><font class=ls-operator>)</font><br /> <font class=ls-statement>Set</font> xlWkSheet <font class=ls-operator>=</font> xlWkBook<font class=ls-operator>.</font>Worksheets<font class=ls-operator>.</font>Add<font class=ls-operator>(</font><font class=ls-operator>)</font><br /><br /> <font class=ls-statement>With</font> xlWkSheet<font class=ls-operator>.</font>ListObjects<br /> xlWkSheet<font class=ls-operator>.</font>Range<font class=ls-operator>(</font><font class=ls-quote>"I1"</font><font class=ls-operator>)</font><font class=ls-operator>.</font><font class=ls-statement>Select</font><br /> <font class=ls-function>Call</font> <font class=ls-operator>.</font>Add<font class=ls-operator>(</font>1<font class=ls-operator>,</font>xlWkSheet<font class=ls-operator>.</font>Range<font class=ls-operator>(</font><font class=ls-quote>"$I:$I"</font><font class=ls-operator>)</font><font class=ls-operator>,</font><font class=ls-operator>,</font>1<font class=ls-operator>)</font><br /> <font class=ls-statement>End</font> <font class=ls-statement>With</font><br /> xlWkBook<font class=ls-operator>.</font>InactiveListBorderVisible <font class=ls-operator>=</font> <font class=ls-constant>False</font><br /></div></pre><br /><br /><div style="FONT-SIZE: 8pt; COLOR: gray; FONT-FAMILY: sans-serif; BORDER: 1 solid Grey; margin : 5px 50px 5px 50px;"><center>This LotusScript was converted to HTML using the <b><i>ls2html</i></b> routine,<br>provided by Julian Robichaux at <a href="http://www.nsftools.com" target="_blank">nsftools.com</a>.</center></div><br />The xl* objects are defined as variants. The last line turns off the borders for the inactive lists. Note that I didn’t worry about naming the list as the VBA script does. I’m not sure if that has any long-term impact or not. The actual code also duplicates the two lines in the With clause for three other columns.<br /><br />When the Excel file opens, the column headings are bolded and, when you click in the column, an arrowhead appears. Click on that and it gives you the unique values in the column plus a few default options (eg. All, Top 10, blanks, etc.).<br /><br />It isn’t perfect since I haven’t figured out how to keep the border hidden when they click on a filtered column nor how to make the arrowhead that indicates a filter is present be visible at all times. But, considering I wasn’t even sure how to do it in the first place, I’ll call it a success.<br /><br /><br />Technorati: <a href="http://technorati.com/tag/show-n-tell thursday" rel="tag">Show-n-Tell Thursday</a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com2tag:blogger.com,1999:blog-24863326.post-22738344431126799202009-10-29T14:27:00.003-04:002009-10-29T14:30:25.288-04:00SnTT: One Thing I've Learned<img src="http://webpages.charter.net/dtmc/images/SNTTbtn.png" align="right" />A few months ago, I developed a new interface to consolidate a number of our applications into what would look like a single-database application. The main part of the interface is a frameset in the “portal” database that consists of a top navigator frame and a bottom “main content” frame. The hotspot links in the top frame execute LotusScript code to write an environment variable to notes.ini that indicates the database server and path, element type and element name that should be opened, then targets the main content frame and opens a single-frame frameset whose content is computed using the environment variable.<br /><br />Still with me? Anyway, this has worked really well with just a few oddities. Object focus is an issue sometimes, and I can’t get everything that opens in that frameset to update the window title properly (they say “Untitled” instead of the name of the application and view).<br /><br />But the biggest problem I had was that some of the applications have buttons to create documents in the background and then display them when the build process is done. This is when the loss of focus becomes an issue. Notes seems to just lose track of where it is and does what appears to the user to be a random change of the view. Plus they don’t get the document (report) they are expecting. I can only attribute this to the nesting of objects (the code is in a button, which is in a view, which is in a frameset, which is in an application, and that application is contained in a frameset in another application).<br /><br />Still there? When the document is built, I use NotesUIWorkspace.EditDocument to open it so the user can see it. The solution to the random (incorrect) behavior is to add the line Call NotesUIWorkspace.SetTargetFrame(“_blank”) before the EditDocument command. This forces the new document to open in a new tab. Plus, it works whether the application containing the code is open within my portal database or in its own tab, as if it were opened from a bookmark or the workspace.<br /><br />I’d post a picture of the portal application, but I’m not sure I’m allowed yet. I will try to get a mockup of something I can post since that may help this make more sense.<br /><br />Technorati: <a href="http://technorati.com/tag/show-n-tell thursday" rel="tag">Show-n-Tell Thursday</a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-25815014475315343182008-09-22T20:37:00.001-04:002008-09-22T20:39:16.203-04:00Does this make me a bad person?I don't think I could care any less that David Blaine's next stunt could leave him blind. And no, I'm not going to link to anything - his 15 minutes should have run out a year ago.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-72884889650247865982008-08-07T13:32:00.001-04:002008-08-07T13:34:57.892-04:00Phone GoodnessI really enjoy my phone. It’s not a Blackberry, but it’s close enough for me. I’ve had my LG Rumor for about 3 months now and find it can do just about everything I want it to. It doesn’t have push email but I don’t get that much important stuff that I need to know immediately when I get a message. The keyboard is great for sending messages and texts (although I’m still not very fast at it because my thumbs are big). I can access Facebook from it and can send Twitter messages and receive Twitter direct messages (that’s all I want at this point). I downloaded the Gmail and Google Maps apps and they work really well. It can play music and videos and takes decent pictures and accepts a micro-SD card for added space. It’s a “smart phone” without being a “smartphone” (which would cost more each month).<br /><br />I wish it could upload pictures to Facebook or let me send them via email, but I think that is more of a Sprint thing than a phone thing.<br /><br />I also got an <a href="http://www.zagg.com/invisibleshield">Invisible Shield</a> to protect the screen. VERY worth the investment in my mind.<br /><br />I don’t know why I wanted to post this. I guess just to say I appreciate the constant advances in phones.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-43254614881620873752008-08-07T13:24:00.002-04:002008-08-07T13:32:42.193-04:00Summer Vacation<a href="http://www.ns-tech.com/blog/geldred.nsf">Gregg</a> has been bugging me (as friends will do) to post about my own Michigan summer vacation adventure since we went to <a href="http://www.ns-tech.com/blog/geldred.nsf/d6plinks/GELD-7GC52H">one of the same places he did</a>. We also went to Mackinac Island but were able to spend more time than Gregg’s family did. It is an annual trip for us (8 of the last 9 years) but this year was different because my Mom and my sister and her family were there with us.<br /><br />We went up on Sunday and stayed a night in Mackinaw City. That would let us decompress from the trip and the kids could swim in the hotel pool. Plus it would get us over to the island earlier and in a less stressed state. We took <a href="http://www.sheplersferry.com">Shepler’s</a> over because they tag the bags and send them directly to our hotel: <a href="http://www.theislandhouse.com">The Island House</a>. We’ve found Shepler’s to be the easiest for us to deal with (but the <a href="http://www.arnoldline.com">Arnold</a> jet-powered catamarans are pretty cool), and we love the bed and breakfast package at the Island House (they have a really good breakfast buffet).<br /><br />Since we’ve been there so often, we definitely have a routine. We brought lunches for everyone and ate in Lafayette Park (at the base of the Fort), then the kids played on the small playground that is there. We got three adult bikes (we brought the other six bikes with us) and started around the island for the first time. Our daughter just learned how to ride on two wheels and she was excited to be riding around on her own. We all rode around the island 5 times while we were there and she made it between 2 and 3 miles on her own each time – pretty good for a 5 year old! Then I got to pull her using the <a href="http://www.trail-gator.com/">Trail-Gator</a> (and answer the usual dozen questions about “where did you get that?”).<br /><br />We have a spot we stop about halfway around the island so we can rest and stretch. And skip stones. Find a flat, round stone of reasonable weight, snap your wrist and see how many times it skips. Tuesday was probably the best day because the water was so calm. I think I hit 15 skips with one stone. Wednesday was fun too because it was really wavy, so we tried to skip from one wave to the next.<br /><br />Dinner one night is at the Ice House, the casual restaurant at the back of the Island House. It is good food and reasonably priced – plus it is out of the way so is not very busy. The second night, we go to 3 Bros. Sarducci for deep dish pizza. Really good stuff! Then, of course, there is fudge!<br /><br />We didn’t go up to Arch Rock this year. We just didn’t all feel like climbing the hills. But I took our daughter through Fort Mackinac for the first time. I hadn’t been in MANY years, so it was interesting to me too. The kids even participated in a bit of a marching drill. Pretty funny watching everyone try to keep up.<br /><br />We have a good time every year we go up. Gregg will attest than I have lots of information to share about Mackinac. I’m glad to share if you want to take a trip yourself.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-7809996858194722072008-06-26T13:04:00.002-04:002008-06-26T13:19:21.072-04:00Weird @TextToTime BehaviorThis isn't really a Show-n-Tell Thursday post, even though it is Thursday. I'm having a problem with a @TextToTime formula and I can't find any documented reason why. When I pass it the string "R. Marshall" it returns 3/1/2008. In fact, if I pass it "Ma", it returns that date. As long as it doesn't have "ma" at the start of any word in the string, it returns nothing (which is what I'd expect).<br /><br />Has anyone else seen that? Can you duplicate it?Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-70830328440895266962008-06-25T13:51:00.004-04:002008-06-25T13:58:10.976-04:00Don't Do This in Notes 8I started writing this the other day but gave up because I wasn't sure what caused this to happen. I'm still not positive, but I have a better idea.<br /><br />I'm running Notes 8.01 on Windows XP SP2. If I turn on the LotusScript debugger, go to my client and open a composite application, like my mail database on the 8 template, I get a debugger window. So far, so good. If I say "Oops, I didn't want the debugger for that" and click the Continue button, the debugger is replaced with a window of my first mail message. That has a title bar and a menu bar but no toolbars, and there is no way to make it go away. I have to kill the client processes and restart to fix it.<br /><br />This only seems to happen (so far) with a composite app. And I haven't done exhaustive testing (because I'm trying to get my projects done!) to know if there is something specific that is a trigger or if it is just something weird about my installation (see my last post for Sametime oddities).<br /><br />I'd be interested to know if anyone else can reproduce this problem.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-22235425344281960922008-06-11T15:55:00.002-04:002008-06-11T16:07:28.671-04:00Have You Seen This in Notes 8.0.1?We have a few people who have moved to the Notes 8.0.1 client and are planning the rollout to the rest of our clients. However, we have been seeing some problems in the client that we can't explain and want to try to sort out before continuing on.<br /><br />The machines we have upgraded are our developer/admin machines, so they had the Notes, Admin and Designer clients installed (all 7.0.2). We did an upgrade rather than uninstalling 7/installing 8 and none of them had an 8 beta installed. These are all Win XP machines. We also had Sametime Connect 7.5.1 installed and I'm not sure if that was uninstalled before installing 8. The one thing we may not have done that is in the installation guide is to stop all other Windows programs before installing.<br /><br />What we are seeing is that the embedded Sametime client does not always start correctly. It will be OK sometimes, but other times will not login and will not allow us to login. Other times it will login but the system tray icon will show as "disconnected". Sometimes when logged in, it will not open a chat window. Restarting the Notes client usually resolves the issues.<br /><br />We can't figure out if it is something to do with how the client was installed on these machines, if it is related to how our environment (OS) is secured or something else. We did have local admin rights on the machines when we installed the software.<br /><br />We're worried about the impression these kinds of things will leave, and we really have no desire to remove all traces of 7 before installing 8 (that seems to resolve the problems) because of the extra work it will cause everyone in setting up their Notes environment again. Any thoughts would be appreciated - no idea is too crazy at this point.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com7tag:blogger.com,1999:blog-24863326.post-79680489422754432202008-04-24T14:14:00.003-04:002008-04-24T14:17:17.777-04:00Shatner Really *is* Speaking at an IBM ConferenceGot an email today about the <a href="http://www-306.ibm.com/software/rational/events/rsdc2008/index.html?S_TACT=105AGX54&S_CMP=B0424&ca=dnw-916">Rational Software Developer Conference</a> and saw that William Shatner is one of the keynote speakers. He's been rumored to be at Lotusphere so often that it's become cliche.<br /><br />I've enjoyed the music at the Lotusphere OGS the last couple of years but I'm a little jealous that the Wallflowers are playing the RSDC. Maybe next year....Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-12150219580972268962008-04-15T07:42:00.002-04:002008-04-15T07:48:52.684-04:00This is a good idea?So Delta and Northwest are going to (try to) merge. Two airlines that not too long ago were in bankruptcy. The CEO of Delta came from Northwest and the CEO of Northwest is going to "retire quietly". They are planning to keep all nine (nine!) of their hubs. Their pilots still haven't come to agreement on their seniority issues.<br /><br />There are obviously a lot of details to be worked out and made public but early on this has the look of 1+1=1. It will be interesting to see where they are going to find the cost savings to justify this. I'm a little worried about smaller airports like the one where I live since we have both Northwest and Delta flying out of here to Detroit, Minneapolis and Cincinnati (and, for a time, Atlanta). I foresee higher prices and fewer choices.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-59851654820881309162008-04-04T15:50:00.004-04:002008-04-04T16:18:10.960-04:00SnTT: @Transform Goodness<img src="http://webpages.charter.net/dtmc/images/SNTTbtn.png" align="right" />If you went to <a href="http://www.lotusgeek.com" target="_blank">Rocky</a>'s session at Lotusphere 2008 on Formula Tricks, you heard about the @Transform function. It lets you take a list of values and run a formula against it to change some or all of the values in the list based on your criteria.<br /><br />I've used it in two places recently and it works far better than anything we could have done prior to the function becoming available (which was in Release 6). In my first example, I have a list of dates and a list of numbers. I want to sum the numbers only for the dates that are in the future. For example, say the fields are:<br />SchedDates is 3/24/08:3/31/08:4/7/08:4/14/08<br />SchedDays is 5:5:4:5<br /><br />If I look at this on 4/4/08, I want to end up with 9. This is the formula I run:<br /><br />@If(SchedDates="";0;@Sum(@Transform(@Text(SchedDates) + "~" + @Text(SchedDays);"x";@If(@TextToTime(@Left(x;"~"))<@Today;0;@TextToNumber(@Right(x;"~"))*8))))<br /><br />That takes the two fields and joins them (eg. 03/24/2008~5:03/31/2008~5:04/07/2008~4:04/14/2008:5), then replaces each one with 0 if the date portion is before today or the number portion if not. So you end up with 0:0:4:5. When you @Sum that, you get 9. Cool!<br /><br />The other time I used it recently was to make sure that a name was placed in a field as long as it wasn't already in that field or five other fields. That formula looks like this and is in the Input Translation of a field (in this case Level5):<br /><br />reqNames:=@Name([Canonicalize];"James Q Public/MyCo/US");<br />@If(reqNames*=Level0:Level1:Level2:Level3:Level4:Level5;@Trim(@Transform(reqNames;"x";@If(@IsMember(x;Level0:Level1:Level2:Level3:Level4:Level5);@Nothing;x)):@ThisValue);<br /> @Trim(reqNames:@ThisValue))<br /><br />The reqNames field can be multi-valued. If any of the values in the field are in any of the listed fields (Level0, etc.), it replaces that value in reqNames with @Nothing. When all values in reqNames are checked, it prepends the remaining names to the field where the formula lives. If not, reqNames is just prepended to the existing field value, making sure there are no blank entries in the list.<br /><br />If you haven't already, be sure you take a look at @Transform.<br /><br />Technorati: <a href="http://technorati.com/tag/show-n-tell thursday" rel="tag">Show-n-Tell Thursday</a>Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com0tag:blogger.com,1999:blog-24863326.post-77066638541652300382008-03-26T08:29:00.003-04:002008-03-26T21:24:36.498-04:00Written Language FoiblesI am accused sometimes - mostly by my wife - of being "Mr. Language Person" because I spot and comment on potentially odd phrases in written or spoken words. I saw this one this morning:<br /><blockquote>SEATTLE — The FBI is analyzing a torn, tangled parachute found buried by children in southwest Washington to determine whether it might have been used by famed plane hijacker D.B. Cooper, the agency said Tuesday.</blockquote><br /><br />I know what this is meant to say, but it could be read three ways, two of them unintended:<br />- The way it is meant, that the children found it.<br />- That there were children buried nearby (ewww).<br />- That the children buried it.<br /><br />I don't know why I notice those things, but I do.<br /><br /><span style="font-weight:bold;">UPDATE:</span> The version published in my local paper reads: <br /><blockquote>SEATTLE — The FBI is analyzing a torn, tangled parachute that children found buried in southwest Washington to determine whether it might have been used by famed plane hijacker D.B. Cooper, the agency said Tuesday.</blockquote><br /><br />Much more clear that way.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1tag:blogger.com,1999:blog-24863326.post-12875545624700345232008-02-18T22:05:00.002-05:002008-02-18T22:11:53.283-05:00MultitaskingI hear a lot about the "new generation" being able to multitask far easier than past generations, primarily because they grow up doing it. I always used to have the TV or music on when I was doing homework, and I still have music on during the day when I am at work, but it tended to fade into the background when I focused on what I *should* have been doing.<br /><br />Today I was looking at some code that I need to enhance and I had a podcast on (after last week's vacation, I am a little behind). I found I could only really concentrate on one or the other because the podcast was one where I might actually learn something (it wasn't just for entertainment).<br /><br />So my question is, can young people now really focus on two tasks like that (working/studying and an informative podcast or TV show)? Or is the multitasking they are talking about studying and IMing friends? I can do that, by the way.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com4tag:blogger.com,1999:blog-24863326.post-31152840832638060792008-02-07T09:13:00.000-05:002008-02-07T09:19:29.883-05:00What I Got From Lotusphere 2008As usual, there was a lot to see and do this year. But, as <a href="http://www.ns-tech.com/blog/geldred.nsf/d6plinks/GELD-7B5FW2">Gregg Eldred</a> and others have said, the Lotusphere experience goes beyond the sessions, Product Showcase and receptions. It really is about the community: sitting at lunch with the people who develop the products, meeting people you have interacted with online, sharing knowledge to resolve that nagging problem. Maybe it’s because I am in a small shop, but knowing other Notes/Domino administrators and developers who I can bounce ideas off is really helpful. There may be communities around other software products, but it seems the bond is stronger within the Lotus community because “community” is what Lotus Notes has always been about.<br /><br />So what did I take away from Lotusphere this year?<br /><br /><ul><li>Developers need to learn Java or make friends with Java developers. That isn’t to say that LotusScript is going away – it isn’t – nor will it become a second-class citizen as an application development language – it won’t. It just means that taking full advantage of the Notes 8 client and the capabilities it can provide will require Java knowledge.</li><br /><br /><li>Widgets (and – maybe – Live Text) will go a LONG way toward making the Notes client the one application people live in all day. The thing I have yet to get a clear picture of is how they will function in a restrictive environment (eg. behind the firewall).</li><br /><br /><li>Designer 8.5 will transform how we develop Notes applications. Yes, there are some paradigm shifts and there may be some syntax issues (do we help Notes developers learn Eclipse terminology or change Eclipse to Notes/Domino terms?), but the tools and flexibility in the new Designer will be phenomenal. I should have spent more time looking at XPages but I think those will evolve into a powerful tool for client applications.</li><br /><br /><li>It will be interesting to see how Lotus Mashups and Bluehouse evolve over the next year. They looked pretty cool “on paper”.</li><br /><br /><li>SpeedGeeking is a must-see. It grew this year vs. last year and I expect it to grow more next year. It is a chance to hear knowledgeable presenters up close and personal as they shred their vocal cords. More importantly, you get a lot of tips on a variety of topics in a short period of time. It is well worth attending.</li></ul><br /><br />The last two years have seen IBM Lotus playing offense in a confident manner. There is a lot of positive energy around Notes/Domino 8 and the roadmap is clearer than it has ever been. To be sure, there are things that could be improved: make it easier to do advanced UI tricks (like using layers), control client and application appearance by merely editing CSS files, Symphony programming and integration (some improvements are coming). But overall, the future looks bright.Don McNallyhttp://www.blogger.com/profile/17995406659448494074noreply@blogger.com1