Welcome to MSDN Blogs Sign in | Join | Help

Deleting a part

In the last post, I showed you how to use the Packaging API to find a particular part and get that part's URI.  The relationship and URI of the particular part are important as you cannot rely on the name of the part being the persisted from save to save.  

One action you can take is removing a part from a package.  For example, removing the VBA project from a macro-enabled file.  I've enclosed a snippet to do this below.  Using this snippet you can remove the VBA project from any Office Open XML file.  Notice that in both the last post and this one, we have yet to touch any of the XML within the parts.  I'll get to that in a future post.

The VBA project is only one of the parts that must require the file to be macro-enabled.  XLM sheets are another.  In a future snippet, I'll show how to remove all the macro parts and convert the file from macro-enabled to macro-free.

/// <summary>

/// Delete the VBA project part and relationship in any file type.

/// </summary>

/// <param name="fileName">name of the file to delete</param>

public void DeleteVBAPart(string fileName)

{

string officeDocRelType = @"http://schemas.microsoft.com/office/2006/relationships/officeDocument";

const string vbaRelationshipType = "http://schemas.microsoft.com/office/2006/relationships/vbaProject";

      PackagePart documentPart = null;

      Uri documentUri = null;

 

      //Open the package with Read permission

      using (Package officePackage = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite))

      {

            //Get the start part

            foreach (PackageRelationship relationship in officePackage.GetRelationshipsByType(officeDocRelType))

            {

// There should only be one document part in the package

                  documentUri = PackUriHelper.ResolvePartUri(new Uri("/", UriKind.Relative), relationship.TargetUri);

                  documentPart = officePackage.GetPart(documentUri);

                  break;

}

            //Find the VBA project part.

            foreach (System.IO.Packaging.PackageRelationship relationship in documentPart.GetRelationshipsByType(vbaRelationshipType))

            {

                  Uri vbaUri = PackUriHelper.ResolvePartUri(documentUri, relationship.TargetUri);

                  PackagePart vbaPart = officePackage.GetPart(vbaUri);

                  //Delete the VBA part

                  officePackage.DeletePart(vbaUri);

                  //Remove the VBA relationship

                  documentPart.DeleteRelationship(relationship.Id);

                  //There is only VBA part:

                  break;

}

 

//Close the package

            officePackage.Close();

}

}

Are you all finding these snippets useful?  Are there specific scenarios you want to see?  Drop me a comment.

Up next:  I'll get into the mailbag and answer some reader questions.

 

Published Wednesday, February 22, 2006 3:09 PM by KevinBoske

Attachment(s): DeleteVBAProject.CS.snippet

Comments

# Programmatically remove parts from an Office file

Kevin Boske has another post on using the System.IO.Packaging assembly to work with the new Office Open...
Thursday, February 23, 2006 11:18 AM by Brian Jones: Office XML Formats

# re: Deleting a part

Sorry everyone, I didn't realize that Anonymous comments were turned off by default.  I've turned them on, you may now comment with impunity.
Thursday, February 23, 2006 1:07 PM by KevinBoske

# re: Deleting a part


Cool. Now that comments are enabled, I can give some feedback.

First thanks for posting. I think it's nice to keep a lot of this stuff in a single place. So far, pages related to this topic are scattered in a number of places, the msdn winfx system io packaging pages, the XPS samples, the SDK itself, complete with a bad rendering experience with msdn when using a certain open source browser. By the way, I think the SDK should be in this blog side bar, handy.

I have a lot of comments, but I'll probably spare you from them from now. One cosmetic request though : the code snippets don't read well because of the indentation (in either IE, Firefox, or a RSS client).

Besides this, since you seem to insist on a "foreach" pattern even when you are really querying a single part of a package, I wonder what the LINQified version of this code looks like.

Friday, February 24, 2006 9:48 AM by Stephane Rodriguez

# re: Deleting a part


Now for a true technical comment. In regards to the API it seems that the separation between a rel id and a part id is publicly exposed in the API. My question is why? Isn't a part uniquely identified by its absolute path?
A corollary to this is that, when you delete a part, you are calling two methods, which means the guts of the SDK are really exposed on the developer. All while I can't see any good reason for that to be the case. Frankly, I would see nothing wrong to be able to say : GetPartById(absolutepath).Delete(), and have the implementation do what you are doing above.

The lack of atomciity calls for troubles in my book. I mean, what about concurrency, failure (the documentation says nothing about what exception might be raised, to the point it makes you wonder if any may be raised at all), rollback?


Friday, February 24, 2006 9:53 AM by Stephane Rodriguez

# re: Deleting a part

Hi Stephane,

Sorry about the code that you see on the blog.  It's an unfortunate side-effect of the blog software we use.  The line width is too small.  If you download and look at the actual snippet in VS, it will look the way it is intended.

I will post something that describes how all of this fits together.  The System.IO.Packaging assembly is designed for use with any Open Packaging Convention file.  Office Open XML files are just an implementation of that spec, as are XPS files.  So, yes, the guts of the SDK are exposed.  
Friday, February 24, 2006 11:10 AM by KevinBoske

# re: Deleting a part


"It's an unfortunate side-effect of the blog software we use."

In fact, taking a look at the htlk source code in this blog kind of proves that the blog engine uses a specialized control to translate a piece of source code into html. It's very different to the other blog content. But they've gotten drunk using MSO styles (oh! the irony). I'd recommend using external syntax highlighters available out there such as http://puzzleware.net/codehtmler/ or http://www.carlosag.net/Tools/CodeColorizer/Default.aspx

Friday, February 24, 2006 4:55 PM by Stephane Rodriguez

# re: Deleting a part


Following BrianJ's answer on being unable to add any non-relationship-aware file to a .(doc,xls,ppt)x file, I wonder if you can shed some light on this for us. Is this enforced when the file is committed, in the .Close() call, or is it up to the developer to ensure that all relationships and parts are properly synched up? Something that would be of interest is a "validation" snippet that can validate whether the resulting file is going to be fine or not next time it's opened in an Office app.

I can see a number of code snippets around parts : factorize identical parts ; delete unused parts ; find signed parts ; rename rel identifiers so that they match the part uris ; get all parts that match an expression defined with Xpath ; same with a regexped- uri ; OLEify/unOLEify a package ; a generic part update mechanism based on a callback ; how many parts ; ...

Friday, February 24, 2006 4:56 PM by Stephane Rodriguez

# re: Deleting a part

Hi Guis,

I am a dat anylist for TAXBACK.COM. I do present my work mostly in Excel. I think the validatio part in the previous comment is a really strong point.

thanks! greetings from Bulgaria
Friday, February 24, 2006 7:26 PM by Pavel

# re: Deleting a part

RE: Blog Software and layout of code:

I think I spoke too soon.  I've been given some pointers by another blogger and I will see if I can get the code to look better over the weekend.  BTW:  The snippets of the code you see in the post are always available for download at the bottom of the post.
Friday, February 24, 2006 7:37 PM by KevinBoske

# re: Deleting a part

Are these libraries exposed to COM, so we can do similar operations using VBA (i.e. from within the Apps)? If not, are there any plans to provide a COM wrapper for it?
Monday, February 27, 2006 12:43 PM by Stephen Bullen

# re: Deleting a part

Steven,
No, these are not exposed through COM.  I'm not sure why you would want to expose the parts and Zip structure through the applications? Once the file is opened in the application, it is loaded into memory. You can already access a lot more of the file through VBA if you have the applications installed.  The packaging APIs are meant for working with the files in the Open Packaging Convention formats.
Monday, February 27, 2006 11:44 PM by KevinBoske

# re: Deleting a part

Kevin,
My thinking is that many of the people who want to be able to process the new XML files are the historical Office power users and developers. I don't think many of them have yet adopted .Net and are doing most of their development in VBA (a language they know well). So I'm not talking about using VBA within a file to modify that same file, but I am talking about being able to write some simple VBA code to loop through a directory and process the files therein. I'm also thinking about a need to pre- or post-process a file being opened/saved in an Office App.

In other words, is there any way we can work with the files in the OPC formats without coding it in .Net?
Tuesday, February 28, 2006 4:42 AM by Stephen Bullen

# re: Deleting a part

There are native third-party Zip libraries available which you could use.

The Packaging API's are part of the Windows Presentation Foundations in WinFX, which is entirely on .NET code. There is no non-managed Packaging API in V1.  
Tuesday, February 28, 2006 6:48 PM by KevinBoske

# re: Deleting a part

Kevin,
While I agree there are third-party zip libraries I could use to crack open the zip file to a temp folder, then use the MSXML library to process them and the zip library to zip it up again, that's extremely messy, probably slow and not that robust. From what I understand of the packaging API, it does all the manipulation in-place, doesn't it? Are there any plans to have a non-managed Packaging API story by the time Office 12 RTMs?
Wednesday, March 01, 2006 1:25 PM by Stephen Bullen

# re: Deleting a part

I haven't looked that closely at any of the other ZIP implementations out there, so I can't comment on their relative merits.  But as I said in the previous response, we will not provide any non-managed Packaging API in V1.

 
Thursday, March 02, 2006 12:49 PM by KevinBoske

# re: Deleting a part

Hi,
I tried to reproduce this excample. I have installed these Software:
- Windows XP SP2 German,
- VS2005,
- Winfx 3.0 Beta2 + Windows SDK.

But on this row:

using (Package officePackage = Package.Open(fileName, FileMode.Open, FileAccess.ReadWrite))

I recieve this Exception:
"Required Types tag not found."

I tried to edit a word-Document produced by the actual 2007 Office System beta.

What have I done wrong?

Regards
Wolle
Wednesday, March 15, 2006 7:36 AM by Wolfgang Meyer

# re: Deleting a part

Wolfgang,

You probably have the February CTP of WinFX, which will work with the Beta 1 Technical Refresh and future versions of the files. Sorry about this, we are a bit out of sync with the WinFX team. To use the Beta1 files, you will have to revert to the Januaray CTP of WinFX, but I recommend waiting for the Technical refresh of Beta1.  
Wednesday, March 15, 2006 8:06 PM by KevinBoske

# re: Deleting a part

It works! Thx.

Is there some documentation about the Package-Classes and the structure of an office document?

Regards
wolle
Tuesday, March 21, 2006 5:12 AM by Wolfgang Meyer

# re: Deleting a part

Not yet, that will be coming with Ecma standardization.  For the time being, you can get sample files from the OpenXMLDevelopers site and Brian, myself, or anyone at the site will be happy to answer any questions.
Friday, March 24, 2006 10:47 PM by KevinBoske

# Learning about Open XML on-line

Links to blog posts that contain useful technical information for developers.  Open XML is a new standard, but there's some good information already available if you know where to look.
Monday, March 27, 2006 11:26 AM by OpenXML Developer
New Comments to this post are disabled
 
Page view tracker