Skip to content

Commit

Permalink
Merge pull request #120 from Numpsy/create_user_properties
Browse files Browse the repository at this point in the history
Add a function to create a new UserDefinedProperties section in a OLE…
  • Loading branch information
ironfede authored Aug 9, 2024
2 parents b4c19c4 + cc4c753 commit 8f9525c
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,41 @@ public void RemoveProperty(uint propertyIdentifier)
properties.Remove(toRemove);
}

/// <summary>
/// Create a new UserDefinedProperties container within this container.
/// </summary>
/// <remarks>
/// Only containers of type DocumentSummaryInfo can contain user defined properties.
/// </remarks>
/// <param name="codePage">The code page to use for the user defined properties.</param>
/// <returns>The UserDefinedProperties container.</returns>
/// <exception cref="CFInvalidOperation">If this container is a type that doesn't suppose user defined properties.</exception>
public OLEPropertiesContainer CreateUserDefinedProperties(int codePage)
{
// Only the DocumentSummaryInfo stream can contain a UserDefinedProperties
if (this.ContainerType != ContainerType.DocumentSummaryInfo)
{
throw new CFInvalidOperation($"Only a DocumentSummaryInfo can contain user defined properties. Current container type is {this.ContainerType}");
}

// Create the container, and add the codepage to the initial set of properties
UserDefinedProperties = new OLEPropertiesContainer(codePage, ContainerType.UserDefinedProperties)
{
PropertyNames = new Dictionary<uint, string>()
};

var op = new OLEProperty(UserDefinedProperties)
{
VTType = VTPropertyType.VT_I2,
PropertyIdentifier = 1,
Value = (short)codePage
};

UserDefinedProperties.properties.Add(op);
this.HasUserDefinedProperties = true;

return UserDefinedProperties;
}

public void Save(CFStream cfStream)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,5 +486,58 @@ public void Test_CLSID_PROPERTY()

}
}

// The test file 'report.xls' contains a DocumentSummaryInfo section, but no user defined properties.
// This tests adding a new user defined properties section to the existing DocumentSummaryInfo.
[TestMethod]
public void Test_ADD_USER_DEFINED_PROPERTIES_SECTION()
{
if (File.Exists("test_add_user_defined_properties.xls"))
File.Delete("test_add_user_defined_properties.xls");

using (CompoundFile cf = new CompoundFile("report.xls"))
{
var dsiStream = cf.RootStorage.GetStream("\u0005DocumentSummaryInformation");
var co = dsiStream.AsOLEPropertiesContainer();

Assert.IsFalse(co.HasUserDefinedProperties);
Assert.IsNull(co.UserDefinedProperties);

var newUserDefinedProperties = co.CreateUserDefinedProperties(65001); // 65001 - UTF-8

newUserDefinedProperties.PropertyNames[2] = "MyCustomProperty";

var newProperty = co.NewProperty(VTPropertyType.VT_LPSTR, 2);
newProperty.Value = "Testing";
newUserDefinedProperties.AddProperty(newProperty);

co.Save(dsiStream);
cf.SaveAs("test_add_user_defined_properties.xls");
}

using (CompoundFile cf = new CompoundFile("test_add_user_defined_properties.xls"))
{
var co = cf.RootStorage.GetStream("\u0005DocumentSummaryInformation").AsOLEPropertiesContainer();

// User defined properties should be present now
Assert.IsTrue(co.HasUserDefinedProperties);
Assert.IsNotNull(co.UserDefinedProperties);
Assert.AreEqual(65001, co.UserDefinedProperties.Context.CodePage);

// And the expected properties should the there
var propArray = co.UserDefinedProperties.Properties.ToArray();
Assert.AreEqual(propArray.Length, 2);

// CodePage prop
Assert.AreEqual(1u, propArray[0].PropertyIdentifier);
Assert.AreEqual("0x00000001", propArray[0].PropertyName);
Assert.AreEqual((short)-535, propArray[0].Value);

// User properties
Assert.AreEqual("MyCustomProperty", propArray[1].PropertyName);
Assert.AreEqual("Testing", propArray[1].Value);
Assert.AreEqual(VTPropertyType.VT_LPSTR, propArray[1].VTType);
}
}
}
}

0 comments on commit 8f9525c

Please sign in to comment.