Skip to content

Commit

Permalink
docs: add sensitivity label example
Browse files Browse the repository at this point in the history
  • Loading branch information
jmcnamara committed Apr 6, 2024
1 parent 3738cbd commit de89109
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 5 deletions.
4 changes: 2 additions & 2 deletions Changes
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ Release 3.0.9 - March 10 2023
-----------------------------

* Add documentation and examples on :ref:`ewx_polars` to demonstrate new `Polars
<https://www.pola.rs>`_ integration of XlsxWriter in `write_excel()`_.
<https://pola.rs/>`_ integration of XlsxWriter in `write_excel()`_.

.. _write_excel(): https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.DataFrame.write_excel.html#polars.DataFrame.write_excel
.. _write_excel(): https://docs.pola.rs/py-polars/html/reference/api/polars.DataFrame.write_excel.html

* Add fix for rare issue with duplicate number formats.

Expand Down
118 changes: 118 additions & 0 deletions dev/docs/source/example_sensitivity_label.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
.. SPDX-License-Identifier: BSD-2-Clause
Copyright 2013-2024, John McNamara, [email protected]
.. _ex_sensitivity_label:

Example: Setting the Sensitivity Label for a Document
=====================================================

This program is an example of adding a Sensitivity Label to an XlsxWriter file. See the
:func:`set_custom_property` workbook method for more details.

Sensitivity Labels are a property that can be added to an Office 365 document to
indicate that it is compliant with a company's information protection policies.
Sensitivity Labels have designations like "Confidential", "Internal use only",
or "Public" depending on the policies implemented by the company. They are
generally only enabled for enterprise versions of Office.

See the following Microsoft documentation on how to `Apply sensitivity labels to
your files and email
<https://support.microsoft.com/en-us/office/apply-sensitivity-labels-to-your-files-and-email-2f96e7cd-d5a4-403b-8bd7-4cc636bae0f9>`_.

Sensitivity Labels are generally stored as custom document properties so they
can be enabled using ``set_custom_property()``. However, since the metadata
differs from company to company you will need to extract some of the required
metadata from sample files.

The first step is to create a new file in Excel and set a non-encrypted
sensitivity label. Then unzip the file by changing the extension from `.xlsx` to
`.zip` or by using a command line utility like this:

.. code-block:: bash
$ unzip myfile.xlsx -d myfile
Archive: myfile.xlsx
inflating: myfile/[Content_Types].xml
inflating: myfile/docProps/app.xml
inflating: myfile/docProps/custom.xml
inflating: myfile/docProps/core.xml
inflating: myfile/_rels/.rels
inflating: myfile/xl/workbook.xml
inflating: myfile/xl/worksheets/sheet1.xml
inflating: myfile/xl/styles.xml
inflating: myfile/xl/theme/theme1.xml
inflating: myfile/xl/_rels/workbook.xml.rels
Then examine the ``docProps/custom.xml`` file from the unzipped xlsx file. The
file doesn't contain newlines so it is best to view it in an editor that can
handle XML or use a commandline utility like libxml’s `xmllint`_ to format the
XML for clarity:

.. _xmllint: https://gnome.pages.gitlab.gnome.org/libxml2/xmllint.html

.. code-block:: xml
$ xmllint --format myfile/docProps/custom.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="2"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_Enabled">
<vt:lpwstr>true</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="3"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_SetDate">
<vt:lpwstr>2024-01-01T12:00:00Z</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="4"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_Method">
<vt:lpwstr>Privileged</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="5"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_Name">
<vt:lpwstr>Confidential</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="6"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_SiteId">
<vt:lpwstr>cb46c030-1825-4e81-a295-151c039dbf02</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="7"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_ActionId">
<vt:lpwstr>88124cf5-1340-457d-90e1-0000a9427c99</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="8"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_ContentBits">
<vt:lpwstr>2</vt:lpwstr>
</property>
</Properties>
The MSIP (Microsoft Information Protection) labels in the ``name`` attributes
contain a GUID that is unique to each company. The "SiteId" field will also be
unique to your company/location. The meaning of each of these fields is
explained in the the following Microsoft document on `Microsoft Information
Protection SDK - Metadata
<https://learn.microsoft.com/en-us/information-protection/develop/concept-mip-metadata>`_.

Once you have identified the necessary metadata you can add it to a new document
as shown below.

Note, some sensitivity labels require that the document is encrypted. In order
to extract the required metadata you will need to unencrypt the file which may
remove the sensitivity label. In that case you may need to use a third party
tool such as `msoffice-crypt`_.

.. _msoffice-crypt: https://github.com/herumi/msoffice



.. literalinclude:: ../../../examples/sensitivity_label.py

1 change: 1 addition & 0 deletions dev/docs/source/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ directory of the XlsxWriter distribution.
example_outline1.rst
example_outline2.rst
example_doc_properties.rst
example_sensitivity_label.rst
example_unicode.rst
example_unicode_polish_utf8.rst
example_unicode_shift_jis.rst
Expand Down
2 changes: 1 addition & 1 deletion dev/docs/source/polars_examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ The following are some of the examples included in the
`examples <https://github.com/jmcnamara/XlsxWriter/tree/master/examples>`_
directory of the XlsxWriter distribution.

They show how to use XlsxWriter with `Polars <https://www.pola.rs>`_ .
They show how to use XlsxWriter with `Polars <https://pola.rs/>`_ .

.. toctree::
:maxdepth: 1
Expand Down
126 changes: 126 additions & 0 deletions dev/docs/source/workbook.rst
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,132 @@ Python type, like in the example above.
Note: the ``name`` and ``value`` parameters are limited to 255 characters by
Excel.

Custom properties can also be used to set Sensitivity Labels. Sensitivity Labels
are a property that can be added to an Office 365 document to indicate that it
is compliant with a company's information protection policies. Sensitivity
Labels have designations like "Confidential", "Internal use only", or "Public"
depending on the policies implemented by the company. They are generally only
enabled for enterprise versions of Office.

See the following Microsoft documentation on how to `Apply sensitivity labels to
your files and email
<https://support.microsoft.com/en-us/office/apply-sensitivity-labels-to-your-files-and-email-2f96e7cd-d5a4-403b-8bd7-4cc636bae0f9>`_.

Sensitivity Labels are generally stored as custom document properties so they
can be enabled using ``set_custom_property()``. However, since the metadata
differs from company to company you will need to extract some of the required
metadata from sample files.

The first step is to create a new file in Excel and set a non-encrypted
sensitivity label. Then unzip the file by changing the extension from `.xlsx` to
`.zip` or by using a command line utility like this:

.. code-block:: bash
$ unzip myfile.xlsx -d myfile
Archive: myfile.xlsx
inflating: myfile/[Content_Types].xml
inflating: myfile/docProps/app.xml
inflating: myfile/docProps/custom.xml
inflating: myfile/docProps/core.xml
inflating: myfile/_rels/.rels
inflating: myfile/xl/workbook.xml
inflating: myfile/xl/worksheets/sheet1.xml
inflating: myfile/xl/styles.xml
inflating: myfile/xl/theme/theme1.xml
inflating: myfile/xl/_rels/workbook.xml.rels
Then examine the ``docProps/custom.xml`` file from the unzipped xlsx file. The
file doesn't contain newlines so it is best to view it in an editor that can
handle XML or use a commandline utility like libxml’s `xmllint`_ to format the
XML for clarity:

.. _xmllint: https://gnome.pages.gitlab.gnome.org/libxml2/xmllint.html

.. code-block:: xml
$ xmllint --format myfile/docProps/custom.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties
xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="2"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_Enabled">
<vt:lpwstr>true</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="3"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_SetDate">
<vt:lpwstr>2024-01-01T12:00:00Z</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="4"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_Method">
<vt:lpwstr>Privileged</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="5"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_Name">
<vt:lpwstr>Confidential</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="6"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_SiteId">
<vt:lpwstr>cb46c030-1825-4e81-a295-151c039dbf02</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="7"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_ActionId">
<vt:lpwstr>88124cf5-1340-457d-90e1-0000a9427c99</vt:lpwstr>
</property>
<property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"
pid="8"
name="MSIP_Label_2096f6a2-d2f7-48be-b329-b73aaa526e5d_ContentBits">
<vt:lpwstr>2</vt:lpwstr>
</property>
</Properties>
The MSIP (Microsoft Information Protection) labels in the ``name`` attributes
contain a GUID that is unique to each company. The "SiteId" field will also be
unique to your company/location. The meaning of each of these fields is
explained in the the following Microsoft document on `Microsoft Information
Protection SDK - Metadata
<https://learn.microsoft.com/en-us/information-protection/develop/concept-mip-metadata>`_.

Once you have identified the necessary metadata you can add it to a new document
as shown below::

import xlsxwriter

workbook = xlsxwriter.Workbook("sensitivity_label.xlsx")
worksheet = workbook.add_worksheet()

# Metadata extracted from a company specific file.
company_guid = "2096f6a2-d2f7-48be-b329-b73aaa526e5d"
site_id = "cb46c030-1825-4e81-a295-151c039dbf02"
action_id = "88124cf5-1340-457d-90e1-0000a9427c99"

# Add the document properties. Note that these should all be in text format.
workbook.set_custom_property(f"MSIP_Label_{company_guid}_Enabled", "true", "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_SetDate", "2024-01-01T12:00:00Z", "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_Method", "Privileged", "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_Name", "Confidential", "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_SiteId", site_id, "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_ActionId", action_id, "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_ContentBits", "2", "text")

workbook.close()


Note, some sensitivity labels require that the document is encrypted. In order
to extract the required metadata you will need to unencrypt the file which may
remove the sensitivity label. In that case you may need to use a third party
tool such as `msoffice-crypt`_.

.. _msoffice-crypt: https://github.com/herumi/msoffice


workbook.define_name()
----------------------
Expand Down
4 changes: 2 additions & 2 deletions dev/docs/source/working_with_polars.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Working with Polars and XlsxWriter
==================================

`Polars <https://www.pola.rs>`_ is a fast dataframe library for Rust and Python.
`Polars <https://pola.rs/>`_ is a fast dataframe library for Rust and Python.

Polars provides very tight integration of XlsxWriter and supports a lot of
features such as conditional formats, tables, autofilters, autofit and others
Expand All @@ -31,7 +31,7 @@ following:

The `write_excel()`_ API is explained in detail in the Polars documentation.

.. _write_excel(): https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.DataFrame.write_excel.html#polars.DataFrame.write_excel
.. _write_excel(): https://docs.pola.rs/py-polars/html/reference/api/polars.DataFrame.write_excel.html

One interesting aspect of the Polars output is that it writes the dataframe as
an :ref:`Excel Data Table <tables>`. We will discuss this and other XlsxWriter
Expand Down
29 changes: 29 additions & 0 deletions examples/sensitivity_label.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
##############################################################################
#
# An example of adding a Sensitivity Label to an XlsxWriter file.
#
# SPDX-License-Identifier: BSD-2-Clause
# Copyright 2013-2024, John McNamara, [email protected]
#
import xlsxwriter

workbook = xlsxwriter.Workbook("sensitivity_label.xlsx")
worksheet = workbook.add_worksheet()

# Metadata extracted from a company specific file.
company_guid = "2096f6a2-d2f7-48be-b329-b73aaa526e5d"
site_id = "cb46c030-1825-4e81-a295-151c039dbf02"
action_id = "88124cf5-1340-457d-90e1-0000a9427c99"

# Add the document properties. Note that these should all be in text format.
workbook.set_custom_property(f"MSIP_Label_{company_guid}_Enabled", "true", "text")
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_SetDate", "2024-01-01T12:00:00Z", "text"
)
workbook.set_custom_property(f"MSIP_Label_{company_guid}_Method", "Privileged", "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_Name", "Confidential", "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_SiteId", site_id, "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_ActionId", action_id, "text")
workbook.set_custom_property(f"MSIP_Label_{company_guid}_ContentBits", "2", "text")

workbook.close()
58 changes: 58 additions & 0 deletions xlsxwriter/test/comparison/test_properties06.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
###############################################################################
#
# Tests for XlsxWriter.
#
# SPDX-License-Identifier: BSD-2-Clause
# Copyright (c), 2013-2024, John McNamara, [email protected]
#

from ..excel_comparison_test import ExcelComparisonTest
from ...workbook import Workbook


class TestCompareXLSXFiles(ExcelComparisonTest):
"""
Test file created by XlsxWriter against a file created by Excel.
"""

def setUp(self):

self.set_filename("properties06.xlsx")

def test_create_file(self):
"""Test the creation of a simple XlsxWriter file."""

workbook = Workbook(self.got_filename)

worksheet = workbook.add_worksheet()

company_guid = "2096f6a2-d2f7-48be-b329-b73aaa526e5d"
site_id = "cb46c030-1825-4e81-a295-151c039dbf02"
action_id = "88124cf5-1340-457d-90e1-0000a9427c99"

workbook.set_custom_property(
f"MSIP_Label_{company_guid}_Enabled", "true", "text"
)
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_SetDate", "2024-01-01T12:00:00Z", "text"
)
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_Method", "Privileged", "text"
)
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_Name", "Confidential", "text"
)
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_SiteId", site_id, "text"
)
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_ActionId", action_id, "text"
)
workbook.set_custom_property(
f"MSIP_Label_{company_guid}_ContentBits", "2", "text"
)

workbook.close()

self.assertExcelEqual()
Binary file not shown.

0 comments on commit de89109

Please sign in to comment.