Welcome to MSDN Blogs Sign in | Join | Help

Fixing up InfoPath exported .mhts in Word

If you export a complex InfoPath view to web archive (.mht) file then edit it in Word, you may notice that Word takes a long time to paginate the document when you switch to print layout for the first time. This is happening because the .mht file has a lot of tall and nested tables spanning across multiple pages and it is hard for Word to layout those tables on pages.

So what can we do about it? Not much from InfoPath side, as most those tables are produced by InfoPath container controls such as repeating sections, lists, etc. However, from Word side, if you think about it, those tables do not serve as containers any more. And if they only have one column, they do not do what tables in Word suppose to do: layout things on pages. So we can just get rid of those (just the grid, we need keep the content of course). And that magic can be performed by the ConvertToText method of Table object, as shown below:

   

Sub UnNestTables()

    Dim tbP As Table

    For Each tbP In ActiveDocument.Tables

       UnNestTable tbP

    Next

End Sub

   

Sub UnNestTable(tbl As Table)

    Dim tblChild As Table

    For Each tblChild In tbl.Tables

        UnNestTable tblChild

    Next

    If tbl.Columns.Count = 1 Then

        tbl.ConvertToText wdSeparateByParagraphs, False

    End If

End Sub

   

After running the "UnNestTables" macro above in Word, all one-column tables will be removed. You should no longer experience the performance lag mentioned above. In addition, you'd find the document looks much neater and easier to work with.

Posted by guowu | 1 Comments

Handy-Dandy Scripts: closing Word gracefully

Sometimes you may find winword.exe process lingering in the memeory and there is no visible Word window that allows you to close it. Believe me, this mostly likely is not Word's fault: chances are that those ghost Word instances are started by some third party applications via automation. But for some reason those applications are not able to terminte the Word instances they brought up. 
 
Now aside from blaming third party applications, what can you do to close Word gracefully? You certainly could kill the process from task manager or other process managing applications. But that is not something called "gracefully": for one thing setting changes you made to Word may get lost. Second if the killed Word instance has modified document open, you will be greeted by the "Document Recovery" taskpane next time you starts Word.
 
In case you don't know, the trick is to use GetObject to connect to the existing Word Application COM object. Running a simple vbscript like the one below should do the job:
 
On Error Resume Next
Do
     Set wd = Nothing
     Set wd = GetObject(, "Word.Application")
     If Not wd Is Nothing Then
          wd.Quit 0 'wdDoNotSaveChanges
     Else
          Exit Do
     End If
Loop
 
Warning: the above script will force Word to quit without saving any changes. If you have unsaved but important changes pending in a "ghost" Word instance, you should use GetObject to connect to the instance first, then save your changes with Word object model.
Posted by guowu | 3 Comments
Filed under:

CSBlogger updates

Haven't touched it for quiet a while, tonight I suddenly feel motivated to fix a few old bugs on CSBlogger and the newest build is now available here.
 
Version Description Credit
1.1.0.38 Bug fixes:
1) Error when retrieving post with an apostrophe(') in the title
2) Error with SetNamedNodeProperty when retrieving posts
3) Post content appears blank when opening the saved xml file
Craig and Scott
 
Besides the fixes I made, there may also be two behavior changes(good or bad) due to changes made on Community Server side(it seems like msdn is now running on CS 1.2):
a) The GetRecentPosts API issue is now fixed.
b) It seems a new bug is introduced with the EnableComments property: it is always set to false when post is retrieved from the server. When updating existing blog entries, please make sure "Enable comments" option is checked if you do want comments turned on.
 
Special notice to Community Server 1.0 users:
Because Community Server 1.1 is now available publicly, I decide not to maintain a separate binary for Community Server 1.0 any more. However, you can always download the source code and compile it for Community Server 1.0 if necessary.
Posted by guowu | 2 Comments
Filed under:

Uninstalling Office updates

Office updates released after today (July 12th, 2005) may be uninstalled like most Windows updates if certain criteria is met. You can find more details in this KB article "Information about the ability to uninstall Office updates". And the very first honorable update that can be uninstalled is Security Update for Word 2002 (KB895589).
Posted by guowu | 0 Comments
Filed under:

Taking snapshots for part of a Word document - the new EnhMetaFileBits property

In Word 2003 object model a new property named EnhMetaFileBits for Range and Selection object is introduced. From the documentation, you'd see that it is supposed to help getting the picture representation for a portion of a Word document. Very interesting, isn't it? However the sample included with Word VBA help is too simple to make any real use of it. I searched the web a little and did not find anything helpful. So I decided to try it out myself to see how it works. And the result? Check out this nice little screenshot:
 
EnhMetaFileBits test screenshot
 
What I did was to create my favorite "rainbow" WordArt in Word, then use EnhMetaFileBits to get its EMF representation and draw that in the picture box on my windows form. The skeleton of my c# code is as following:
 
using Office = Microsoft.Office.Core;
using Word = Microsoft.Office.Interop.Word;
 
object missing = System.Reflection.Missing.Value;
 
// Get the Graphics object from the picture box
Graphics g = pictureBox1.CreateGraphics();
// Clear the picture box
g.Clear(pictureBox1.BackColor);
g.DrawString("Starting Microsoft Word, please wait...",this.Font,new SolidBrush(Color.Black),new PointF(0F,0F));
 
// Start a new Word instance if necessary
if (wdApp == null)
wdApp = new Word.ApplicationClass();
// Create a new document
Word.Document wdDoc = wdApp.Documents.Add(ref missing, ref missing, ref missing, ref missing);
 
// Add a WordArt with text from textBox1 to the new document
Word.Shape wdShape = wdDoc.Shapes.AddTextEffect(
    Office.MsoPresetTextEffect.msoTextEffect16, //the rainbow wordart
    this.textBox1.Text, "Arial Black", 16,
    Office.MsoTriState.msoFalse, Office.MsoTriState.msoFalse,
    0, 0, ref missing);
// Select the shape so that EnhMetaFileBits can be retrieved from the Selection object
// This is unnecessary if you have a Range object handy
wdShape.Select(ref missing);
 
// Create a meta file using the byte array returned from EnhMetaFileBits
byte[] emfData = (byte[])wdApp.Selection.EnhMetaFileBits;
System.IO.MemoryStream ms = new System.IO.MemoryStream(emfData);
Metafile mf = new Metafile(ms);
 
// Draw the meta file in the picture box
g.Clear(pictureBox1.BackColor);
g.DrawImageUnscaled(mf, 0, 0);
g.Dispose();
 
As you can see it is pretty easy and straigtforward. However, there is one caveat: the Metafile object created this way may be much wider than it should be: a very big extra white margin may appear to the right. That is why I am using the DrawImageUnscaled method to crop the image. I am still trying to figure out the cause. It might be something I did wrong because I know very little about System.Drawing namespace. Any GDI experts out there care to comment?
 
The sample VS.Net 2003 solution is available for download here.
Posted by guowu | 6 Comments
Filed under:

RSS feeds for KB articles

Normally I don't point people around. This one is too good to miss though: Microsoft is introducing RSS feeds that list the most recently published KB articles for many products.
 
[Update] - I took the time to create the OPML so that you don't need to copy/paste the feeds into your news reader. You can get it here.
Posted by guowu | 1 Comments
Filed under:

Authoring XML schema (XSD) with InfoPath - Part II

Like I mentioned earlier, it is very easy to use InfoPath as an XML schema editor, with very little extra work:
 
  1. Choose Design a form… from the File Menu in InfoPath.
  2. In the Design a new form task pane, select New Blank Form. Note, if you want to derive a schema from existing XML document or data connection, choose one of the New from… options and skip to step 4) below.
  3. On the Design Tasks pane, click on Data Source to show the Data Source Pane. Right click on the myFields element, you will see a shortcut menu. Starting there, you can create data source structure that models your need.
  4. Once you are done, go to File menu, Extract form files…, then quit InfoPath. Go to the folder you just saved extracted form files, you should find myschema.xsd is what you want. Note: if you are deriving a schema, the schema you want may not be defined directly inside myschema.xsd, but imported there.
  5. (Optional) Open myschema.xsd in your favorite XML or text editor, remove the my namespace auto-generated by InfoPath or replace it with your desired namespace URI.
 
And that is it!

Have a nice day and thanks for listening to me murmuring!
Posted by guowu | 2 Comments
Filed under:

CSBlogger 1.1 is released!

Available now here. I am little bit surprised that CSBlogger didn't get much attention as its .Text cousin SimpleBlogger had. So I decide to list a few reasons why you should consider using CSBlogger  as your Community Server blog editor:
 
1) It provides features that are standard in Microsoft Office application, but not available in most blog clients, including: format painter, undo/redo, spell checker, auto-correction, etc.;
2) It has full offline support, which means you can blog on the go;
3) It has the nice look and feel of web pages, and good user experience of standalone windows application. Personally I think it is pretty cool. Take a look at screenshots, and see whether you disagree with me.
4) The "Insert Picture" and "Paste Html" issue in SimpleBlogger has been workaround in the latest release;
5) Oh, the new release allows you specify a signature for your blogs, like the one you see at the end of this post;
...
 
Ok, better stop now. Also stopped should be updates on CSBlogger releases. Now that everything I want it to do is in place, I think I can get some rest now. But, if you find any bugs, please let me know.

Have a nice day and thanks for listening to me murmuring!
Posted by guowu | 8 Comments
Filed under:

Community Server Issues - Part II

A while back, I complained about the big pain caused by the SOAP header change between Community Server 1.0 and 1.1 web service APIs. Scott was kind enough to explain why they made the change. Still, getting my blog editor to work with both versions is painful. At first I went for the easy route and created separate editions for each version. It turned out to be very silly and annoying to maintain two almost identical copies of the code. So I decided to bite the bullet and use conditional compilation to merge the code together. The process was smooth but tedious; those "#if…#else…#endif" clauses scattered everywhere really do not look pretty. After all, it worked fine and now I have one code base to work with. You will see the combined source code uploaded a few days after I am done with a major update on CSBlogger. Stay tuned if you are interested.
 
Anyway, back to the topic. At the time I posted the first one, the next issue I planned to talk about was that Community Server strips out all style formatting in blog entries. That, after a few weeks, seems to me not as bad as it originally appeared. I guess the point is that blogging is not web publishing and bloggers should try to keep their posts clean and plain. I don't necessarily agree with this but can live with it. Just that tables in my old posts now look so horrible that I had to change the custom CSS for my blog to make them at least look ok.
 
That leaves me with two remaining issues. Both on the blogservice web service API of Community Server:
  • the GetRecentPosts API turns out to be "GetOldPosts": it always return the oldest n posts if given n as the number of posts to retrieve from the server. This would make my blog editor too hard to use for those long time bloggers because they will have to retrieve all their blog entries to get the latest one. I don't know whether this happens also with the GetRecentArticles API;
  • the value of the Date field in a BlogPost is off several hours even though I had set the time zone in my user options. To workaround this, I had to manually add/substract a certain value to the date.
 
I hope those two are not my mistakes. :-) That is all I have in mind for now. Next time I will post some suggestions and feature requests on the web service APIs.
 
[Update] Just found one more issue: the "IsPublished" value of a BlogPost is always true when calling GetRecentPosts.

Have a nice day and thanks for listening to me murmuring!
Posted by guowu | 3 Comments
Filed under:

Authoring XML schema (XSD) with InfoPath - Part I

Recently, I ran across Aaron Skonnard's MSDN magazine articles talking about Contract First Service Development. The very first step of this so called "Contract-First" development process is to create the XML schema. And for that, Aaron recommended Visual Studio as one of the XSD editor. This reminds me to mention a frequently overlooked fact that Microsoft InfoPath actually works great as an XSD authoring tool.
 
The biggest advantage of using InfoPath as an XSD editor is, IMHO, the WYSIWYG user interface:
 
As the screenshot above shows, you can create, modify and visualize your data structure very easily. It will be a tremendous help if you are not so familiar with XML schema.
 
The other big, big plus is that InfoPath can derive XML schema for you: provide an xml file, a web service (well, I know this is a little bit redundant, just for the record), or even a database connection, and you are all set!
 
I hope that is enough to get you interested. Before we move on and talk about how to use InfoPath to create XML schemas, you should also be aware of the con's:
1) This is not an intended functionality of InfoPath. So you will have to do a little extra (very little, I promise) work.
2) Some XSD constructs are not supported by InfoPath. See details in this MSDN article: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odc_ip2003_ta/html/ODC_INFInfoPathXSD.asp
 
Ok, next post I will talk in details about how to do this. While on the topic, I'd point out that InfoPath is also great for XSL editing because of the WYSIWYG UI. You will have to clean up all those InfoPath specific styles definition though. My other favorite XSL editor is Microsoft FrontPage 2003: its intellisence extension for XSL is a huge relief, not to mention you also get a rich set of XML editing features.
Posted by guowu | 5 Comments
Filed under:

Updates on CSBlogger and source code release

Some minor bug fixes are made. As always, the new build can be downloaded here. The source code is also posted there upon requests. You will find the source for the Community Server 1.0 edition under the "CS1.0" sub folder.
 
In the future, I might do a few blog entries on how the whole thing was designed and created. Don't hold your breath on it though: I am pretty occupied these days.
 
 

This post is provided "AS IS" with no warranties, and confers no rights. Use of materials found in this post is subject to the terms specified in the Terms of Use.
Posted by guowu | 1 Comments
Filed under:

Creating LEAN_AND_MEAN Virtual Hard Disk (.vhd) Files

Not so recently I discovered a way that can significantly reduce VHD file sizes: I was able to reduce the sizes of all my VHDs down to 100MB or less bigger than what their guest operating systems report. Just today I compacted a Japanese Windows XP SP2 VHD  with a OS reported size of 1.70GB to 1.72GB, whereas the standard procedure can only get down to about 2.3GB. If you are obsessed, like me, in reducing the size of bloated VHDs, you'd know this result is just amazing.
 
The secret turns out to be very simple. As you may already know, the standard procedure to compact dynamic expanding VHDs is as the following:
 
1) Inside the VM, run disk defragmenter
2) Inside the VM, run Virtual Disk Precompactor or other disk utility program to "zero out" deleted data
3) Shutdown the VM, run "Virtual Disk Wizard" from VPC console to compact the VHD.
 
And the key lies in step 1. Instead of using the defragmenter comes with Windows, you should use the one created by Dave Whitney, which can be download for free here. The special thing about Dave's defragmenter is that it can defrag not only occupied spaces, but also free spaces. If you think about it, this totally makes sense why it helps compacting the VHDs. So far my experience is that no matter how the image is built and how bloated the virtual disk is, this procedure will give you the real size!
 
Of course, nothing comes without cost. From my experience, it takes 5 to 10 more minutes to finish than the Windows defragmenter. It could take much longer if the disk size is bigger. However, considering the huge saving on disk spaces(500MB per disk at the least) and the network bandwidth if you are distributing them to others, it is definitely worth the extra wait. What is more, I suspect the guest OS performance would be better. No hard evidence on that though.
 
One thing to clarify: I usually relocate page files to a secondary virtual disk therefore all disk sizes I mentioned here do not include the page files: because they usually have big reported sizes, but actually take little space on the disk, it may give you false sense of compactness. If you ever make the size of your VHD smaller than what guest OS reports, I am almost certain that you have page files included in the equation.
 
At last, this is totally my personal experience (and opinion). Your experience may vary. I would be very interested to know how it works on very big VHDs. So please do report back your result if you try this on VHDs bigger than 8G, 10G, or maybe even 16G.
Posted by guowu | 13 Comments
Filed under:

Community Server Issues - Part I

Ok, seriously, I have encountered several problems on the web service APIs provided by Community Server during the process of creating this InfoPath blog client. It seems to me the forum at communityserver.org is not very active. Therefore I am posting it here in hope of getting someone's attention.
 
Some of those issues I believe are bugs, some of them might be design changes. But what I really, really do not understand is the soap header change between CS1.0 and the CS version on http://blogs.msdn.com (I believe the latter is newer, pre 1.1, maybe?). Take a look, here is the CS1.0 header:
 
  <soap:Header>
    <BlogCredentials xmlns="http://communityserver.org/blogs/services/posts/">
      <Username>string</Username>
      <Password>string</Password>
      <Blogname>string</Blogname>
    </BlogCredentials>
  </soap:Header>
and here is the msdn one:
 
  <soap:Header>
    <ServiceCredentials xmlns="http://communityserver.org/blogs/services/posts/">
      <Username>string</Username>
      <Password>string</Password>
      <SectionName>string</SectionName>
    </ServiceCredentials>
  </soap:Header>
Due to this change, the client proxy classes of both versions are totally incompatible to each other. In order to work with both, you'd go through two code paths for each web service calls. (Well, someone familiar with reflection might do better, but I doubt it). I, actually ended up creating a separate edition for each of them. What a pain…
 
Of course, there are a few other changes made in the newer versions. Most of them are meaningful and easy to accommodate. For example, the ModerateComments property of the BlogPost class is now changed to a ModerationType enumeration. The functional improvement is obvious. Now what could you get by just changing namings in a published API set, besides introducing incomptabilities?
 
 
Posted by guowu | 7 Comments
Filed under:

CSBlogger Take 2

Finally I was able to get CSBlogger also working with Community Server 1.0. In the mean time, a few minor bug fixes are made to make both the blogs.msdn.com and the CS1.0 edition. The new build is released at the same location here. Hopefully it will be stable enough for a while. Now I have some serious complaints on Community Server coming…
Posted by guowu | 2 Comments
Filed under:

Here comes the CSBlogger

The download link and other information for CSBlogger, an InfoPath client for Community Server blogs, is now available here. Please post a comment under this post if you have questions or find bugs.
Posted by guowu | 15 Comments
Filed under:
More Posts Next page »
 
Page view tracker