{"id":253954,"date":"2015-03-27T19:36:02","date_gmt":"2015-03-27T15:36:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=253954"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=253954","title":{"rendered":"Python, xlsx \u0441 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u043c\u0438, \u043c\u0430\u043a\u0440\u043e\u0441\u0430\u043c\u0438, media-art, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438"},"content":{"rendered":"<p>     \t\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e, \u0445\u0430\u0431\u0440\u043e\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<p>  \u0420\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 python \u0441 xlsx.<br \/>  \u0414\u0430, \u044f \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u043f\u0440\u043e \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u044f \u043d\u0435 \u0441\u043c\u043e\u0433 \u043d\u0430\u0439\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438.<br \/>  \u041d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u044f\u0447\u0435\u0435\u043a \u0443 \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 xls.<\/p>\n<p>  \u0412\u0441\u0435 \u0431\u044b \u043d\u0438\u0447\u0435\u0433\u043e, \u043d\u043e \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b \u043c\u0430\u043a\u0440\u043e\u0441\u044b, \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438, \u043e\u0431\u044a\u0435\u043a\u0442\u044b media-art, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u043c\u043d\u043e\u0433\u043e \u0447\u0435\u0433\u043e \u0435\u0449\u0435.<br \/>  \u041f\u0435\u0440\u0435\u0431\u0440\u0430\u0432 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f (openpyxl, xlutils.copy \u0438 \u043f\u0430\u0440\u0443 \u0434\u0440\u0443\u0433\u0438\u0445), \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043e\u043d\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u044f\u0442 \u0444\u0430\u0439\u043b.<br \/>  \u0410 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0432\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043a \u0442\u043e\u0447\u0435\u0447\u043d\u043e\u0439 \u043f\u0440\u0430\u0432\u043a\u0435 \u044f\u0447\u0435\u0435\u043a \u0438 \u0447\u0442\u043e\u0431 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043a\u0430\u043a \u0431\u044b\u043b\u043e.<\/p>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<p>  \u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f<\/p>\n<p>  \u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0447\u0442\u043e \u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u0430\u043d\u043a\u0430 \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0435 \u043d\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b <br \/>  \u0434\u043b\u044f \u043f\u0440\u0438\u043d\u044f\u0442\u0438\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e \u0432\u044b\u0434\u0430\u0447\u0435 \u043a\u0440\u0435\u0434\u0438\u0442\u0430.<br \/>  \u0415\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u0444\u0430\u0439\u043b excel, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u043b\u0441\u044f \u043f\u043e \u043d\u0430\u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0443 \u0438\u0437 \u043d\u0435\u0437\u043e\u043f\u0430\u043c\u044f\u0442\u043d\u044b\u0445 \u0432\u0440\u0435\u043c\u0435\u043d<br \/>  \u0438 \u043f\u0440\u043e\u0448\u0435\u043b \u0447\u0435\u0440\u0435\u0437 \u0440\u0443\u043a\u0438 \u00ab\u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c \u043c\u043d\u043e\u0433\u043e\u00bb \u00ab\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432 \u043d\u0430 Excel\u00bb.<\/p>\n<p>  \u0418 \u043d\u0443\u0436\u043d\u043e \u043a\u0430\u043a-\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432 \u0431\u0430\u043d\u043a \u0437\u0430\u044f\u0432\u043a\u0438 \u043d\u0430 \u043a\u0440\u0435\u0434\u0438\u0442.<br \/>  \u0422\u043e \u0435\u0441\u0442\u044c, \u043d\u0443\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b, \u0432\u0431\u0438\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u043e \u043f\u043e\u0447\u0442\u0435.<\/p>\n<p>  \u042f \u043f\u043e\u0434\u0443\u043c\u0430\u043b \u00ab\u043d\u0435 \u044f \u043f\u0435\u0440\u0432\u044b\u0439, \u043d\u0438 \u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439\u00bb \u0438 \u043f\u043e\u0448\u0435\u043b \u0438\u0441\u043a\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<br \/>  \u0422\u0443\u0442 \u0432\u0441\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u043e.<br \/>  openpyxl:<br \/>   \u043f\u043e\u0447\u0435\u043c\u0443-\u0442\u043e \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b \u043e\u0431\u0432\u043e\u0434\u043a\u0443 \u044f\u0447\u0435\u0435\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0434\u0430\u0436\u0435 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u043b (\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u043b \u0433\u0440\u0430\u043d\u0438\u0446\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u043b\u0435\u0432\u043e\u0433\u043e \u0443\u0433\u043b\u0430)<br \/>   \u0414\u0430\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 keep_vba=True, \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u0438\u0441\u044c \u00ab\u0431\u0438\u0442\u044b\u0435\u00bb \u0444\u0430\u0439\u043b\u044b xlsm (\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043c\u0430\u043a\u0440\u043e\u0441\u044b)<br \/>  xlutils:<br \/>   \u0422\u0435\u0440\u044f\u043b \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b media-art \u0438 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 xls, \u0432\u043c\u0435\u0441\u0442\u043e xlsm<br \/>  \u041f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0432 \u0435\u0449\u0435 \u043f\u0430\u0440\u0443 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432, \u044f \u0440\u0435\u0448\u0438\u043b \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u043b\u044c\u043d\u0438\u043a\u043e\u043c, \u0433\u0430\u0435\u0447\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0441\u0432\u043e\u0435\u0433\u043e \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u0430 \u0441 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u043e\u0439 \u0441\u0435\u0434\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043d\u043e\u0440\u043e\u0432\u0438\u0442 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u043f\u0430\u0440\u044b \u043b\u0438\u0448\u043d\u0438\u0445 \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e.<\/p>\n<p>  \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0437\u0430\u0434\u0430\u0447\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430, <br \/>  \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e zip-\u0430\u0440\u0445\u0438\u0432 \u0441 \u043a\u0443\u0447\u043a\u043e\u0439 XML-\u0435\u043a.<br \/>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u0437\u0430\u043f\u0430\u043a\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u044d\u0442\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u043e, \u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u0430\u043a \u0431\u044b\u043b\u043e.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u043f\u043e\u0435\u0445\u0430\u043b\u0438<\/p>\n<p>  \u041d\u0430\u043c \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f ZipFile, lxml \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e.  <\/p>\n<pre><code class=\"python\">import os import re from datetime import datetime, date from StringIO import StringIO from zipfile import ZipFile, ZIP_DEFLATED from lxml import etree <\/code><\/pre>\n<p>  \u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440.<br \/>  \u0421\u0440\u0430\u0437\u0443 \u0443\u0437\u043d\u0430\u0435\u043c, \u0433\u0434\u0435 \u043b\u0435\u0436\u0430\u0442 \u043d\u0430\u0448\u0438 \u043b\u0438\u0441\u0442\u044b, \u0432\u044b\u0437\u0432\u0430\u0432 self._get_sheet_locations()<br \/>  \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043a\u0443 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u043e\u043c\u0435\u0440\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437 \u0438\u043d\u0434\u0435\u043a\u0441\u0430 \u044f\u0447\u0435\u0439\u043a\u0438<\/p>\n<pre><code class=\"python\">def __init__(self, zip_folder):     u&quot;&quot;&quot;     @param zip_folder: \u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b xlsx     \u0422\u043e \u0435\u0441\u0442\u044c \u0444\u0430\u0439\u043b '[Content_Types].xml' \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438     &quot;&quot;&quot;     self._zip_folder = zip_folder     self._data = {}     self._zip_stream = StringIO()     self._row_finder = re.compile(r'\\d+$')     self._namespaces = {         'ws': 'http:\/\/schemas.openxmlformats.org\/spreadsheetml\/2006\/main',         'rel': 'http:\/\/schemas.openxmlformats.org\/package\/2006\/relationships'     }      self._sheet_paths = self._get_sheet_locations()          # \u0421\u043b\u043e\u0432\u0430\u0440\u044c \u0441\u0442\u0440\u043e\u043a     self._shared_strings = None     self._shared_strings_root = None     self._shared_strings_index = None <\/code><\/pre>\n<p>  \u0414\u0435\u043b\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0441\u0442\u0430\u0435\u0442 \u043d\u0430\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b lxml etree <br \/>  \u043f\u043e \u043f\u0443\u0442\u0438 \u043a \u0444\u0430\u0439\u043b\u0443 xml, \u0447\u0442\u043e\u0431 \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f  <\/p>\n<pre><code class=\"python\">def _get_xml(self, file_path):     u&quot;&quot;&quot;      \u0412\u044b\u0442\u0430\u0449\u0438\u0442\u044c XML-\u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u043f\u0430\u043f\u043a\u0438 \u043f\u043e \u043f\u0443\u0442\u0438      @param file_path: \u041f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430     &quot;&quot;&quot;     return etree.parse(os.path.join(self._zip_folder, file_path)) <\/code><\/pre>\n<p>  \u0421\u0442\u0440\u043e\u043a\u0438 \u0432 xlsx \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435. <br \/>  \u0412 \u044f\u0447\u0435\u0439\u043a\u0430\u0445 (\u0443\u0437\u043b\u0430\u0445 xml) \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435.<br \/>  \u042d\u0442\u043e \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u0430\u0440\u0445\u0438\u0432\u0430\u0442\u043e\u0440.<\/p>\n<p>  \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0441\u043b\u043e\u0432\u0430\u0440\u044c.<br \/>  \u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442 xml, \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<p>  \u042d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u043d\u043e \u043c\u044b \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043a\u0430\u0442\u044c, \u0435\u0441\u0442\u044c \u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e.<br \/>  \u0422\u0430\u043a \u043a\u0430\u043a \u043e\u0431\u044a\u0435\u043c \u0432\u043d\u043e\u0441\u0438\u043c\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 (\u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043a\u043e\u043b-\u0432\u043e\u043c \u0441\u0442\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u0444\u0430\u0439\u043b\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c),<br \/>  \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0435\u0449\u0435 \u043e\u0434\u043d\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>  \u041d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <br \/>  _shared_strings (\u043f\u043e\u0442\u043e\u043c \u0438\u0437 \u043d\u0435\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u043d\u044b\u0439 \u0441\u043b\u043e\u0432\u0430\u0440\u044c)<br \/>  _shared_strings_root \u2014 \u0432 \u043d\u0435\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438<br \/>  _shared_strings_index \u2014 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441 (\u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u0447\u0435\u0442\u0447\u0438\u043a\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438)  <\/p>\n<pre><code class=\"python\">def _init_shared_strings(self):     u&quot;&quot;&quot;      \u041b\u0435\u043d\u0438\u0432\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043e \u0441\u043b\u043e\u0432\u0430\u0440\u0435\u043c \u0441\u0442\u0440\u043e\u043a.     \u041b\u0435\u043d\u0438\u0432\u043e - \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f.     \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 self._add_shared_string     &quot;&quot;&quot;     self._shared_strings = self._get_xml('xl\/sharedStrings.xml')     self._shared_strings_root = self._shared_strings.xpath('\/ws:sst', namespaces=self._namespaces)[0]     self._shared_strings_index = int(self._shared_strings_root.attrib['uniqueCount']) <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c \u0438 \u0432\u0435\u0440\u043d\u0435\u043c \u0435\u0435 \u0438\u043d\u0434\u0435\u043a\u0441.<br \/>  \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439  <\/p>\n<pre><code class=\"python\">def _add_shared_string(self, value):     u&quot;&quot;&quot;      \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c sharedStrings     \u041d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0442\u0443\u0442 \u0431\u044b\u0442\u044c.     \u041d\u043e \u0438\u0437-\u0437\u0430 \u043c\u0430\u043b\u043e\u0433\u043e \u043a\u043e\u043b-\u0432\u0430 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u043f\u043e\u0444\u0438\u0433\u0443 \u043d\u0430 \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u043d\u0438\u0435 \u0441\u043b\u043e\u0432\u0430\u0440\u044f.     uniqueCount \u0438 Count \u043d\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 (\u0438 \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442)      @param value: \u0421\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c     @return: \u0418\u043d\u0434\u0435\u043a\u0441 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435 sharedStrings     &quot;&quot;&quot;     if self._shared_strings is None:         self._init_shared_strings()      node_t = etree.Element('t')     node_t.text = value      node_si = etree.Element('si')     node_si.append(node_t)      self._shared_strings_root.append(node_si)     self._shared_strings_index += 1      return (self._shared_strings_index - 1) <\/code><\/pre>\n<p>  \u0421\u043e\u0431\u0435\u0440\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u043a\u0430\u043a\u043e\u0439 \u043b\u0438\u0441\u0442 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0430\u0440\u0445\u0438\u0432\u0435.<br \/>  \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u043e 2-\u043c XML-\u0444\u0430\u0439\u043b\u0430\u043c:<br \/>   \u2014 xl\/workbook.xml<br \/>   \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432 \u043a\u043d\u0438\u0433\u0435 \u0435\u0441\u0442\u044c<br \/>   \u2014 xl\/_rels\/workbook.xml.rels<br \/>  \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u0442\u043e\u043c, \u0433\u0434\u0435 \u0432\u0441\u0435 \u044d\u0442\u043e \u043b\u0435\u0436\u0438\u0442  <\/p>\n<pre><code class=\"python\">def _get_sheet_locations(self):     u&quot;&quot;&quot;      \u0423\u0437\u043d\u0430\u0435\u043c \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043b\u0438\u0441\u0442\u044b     @return: \u0421\u043b\u043e\u0432\u0430\u0440\u044c. {\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u043b\u0438\u0441\u0442\u0430: \u043f\u0443\u0442\u044c_\u043a_xml}     &quot;&quot;&quot;          # \u041a\u043d\u0438\u0433\u0438     sheets_id = {}     workbook_xml = self._get_xml('xl\/workbook.xml')     for sheet_xml in workbook_xml.xpath('\/ws:workbook\/ws:sheets\/ws:sheet', namespaces=self._namespaces):         sheet_name = sheet_xml.attrib['name']         sheet_rid = sheet_xml.attrib['{http:\/\/schemas.openxmlformats.org\/officeDocument\/2006\/relationships}id']         sheets_id[sheet_rid] = sheet_name      # \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432     paths = {}     xml = self._get_xml('xl\/_rels\/workbook.xml.rels')     for node in xml.xpath('\/rel:Relationships\/rel:Relationship', namespaces=self._namespaces):         r_id = node.attrib['Id']         path = os.path.join('xl', node.attrib['Target'])          if r_id in sheets_id:             sheet_label = sheets_id[r_id]             paths[sheet_label] = path      return paths <\/code><\/pre>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0435\u043c zip-\u0430\u0440\u0445\u0438\u0432, \u0441\u043e\u0431\u0438\u0440\u0430\u044f \u0432 \u043d\u0435\u0433\u043e \u0432\u0441\u0435 \u0444\u0430\u0439\u043b\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043c\u0435\u043d\u044f\u043b\u0438\u0441\u044c (\u0431\u0435\u0437 exclude_files)  <\/p>\n<pre><code class=\"python\">def _create_base_zip(self, exclude_files):     u&quot;&quot;&quot;      \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0432 \u043f\u0430\u043f\u043a\u0435 zip_folder \u0434\u043b\u044f \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.     \u0412 \u043d\u0435\u0433\u043e \u043d\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 \u043b\u0438\u0441\u0442\u044b \u0441 \u0438\u0437\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u044f\u0447\u0435\u0439\u043a\u0430\u043c\u0438.     \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0442\u0443\u0434\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 _add_changes     @param exclude_files: \u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432     @return: \u043e\u0431\u044a\u0435\u043a\u0442 ZipFile     &quot;&quot;&quot;      zip_file = ZipFile(self._zip_stream, mode='a', compression=ZIP_DEFLATED)      for path, dirs, files in os.walk(self._zip_folder):         rel_path = path[len(self._zip_folder):]                  for file_name in files:             if rel_path == '':                 zip_name = file_name             else:                 zip_name = os.path.join(rel_path, file_name)              if zip_name not in exclude_files:                 zip_file.write(os.path.join(path, file_name), zip_name)      return zip_file <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u043b\u0438\u0441\u0442\u044b \u0432 zip-\u0444\u0430\u0439\u043b, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b\u0439 \u0432 \u0432\u0438\u0434\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430.<br \/>  \u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0432\u0441\u0435 \u043d\u0430\u043a\u043e\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043b\u0438\u0441\u0442\u0430\u043c, \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u043b\u0438\u0441\u0442\u044b \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0445 \u0432 \u0430\u0440\u0445\u0438\u0432  <\/p>\n<pre><code class=\"python\">def _add_changes(self, zip_file):     u&quot;&quot;&quot;      \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.     \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b\u044b \u0438 \u0437\u0430\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u0445 \u0432 zip \u043f\u043e\u0432\u0435\u0440\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e      @param zip_file: \u043e\u0431\u044a\u0435\u043a\u0442 ZipFile \u0431\u0435\u0437 \u043b\u0438\u0441\u0442\u043e\u0432, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u044f\u0447\u0435\u0439\u043a\u0438     &quot;&quot;&quot;          # \u041e\u0431\u0445\u043e\u0434\u0438\u043c \u043b\u0438\u0441\u0442\u044b \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c     for sheet_name, data in self._data.items():         sheet_file = self._sheet_paths[sheet_name]                  sheet_content = self._get_changed_sheet(sheet_file=sheet_file, data=data)         zip_file.writestr(sheet_file, sheet_content) <\/code><\/pre>\n<p>  \u0412\u043d\u043e\u0441\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043b\u0438\u0441\u0442 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 XML \u0441 \u0432\u043d\u0435\u0441\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438  <\/p>\n<pre><code class=\"python\">def _get_changed_sheet(self, sheet_file, data):     u&quot;&quot;&quot;      \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 ZIP-\u0430\u0440\u0445\u0438\u0432      @param sheet_file: \u041f\u0443\u0442\u044c \u043a xml-\u0444\u0430\u0439\u043b\u0443 \u0441 \u043b\u0438\u0441\u0442\u043e\u043c     @param data: \u0421\u043b\u043e\u0432\u0430\u0440\u044c \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438 {cell: value}     @return: xml-\u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u043c \u043b\u0438\u0441\u0442\u043e\u043c     &quot;&quot;&quot;      xml = etree.parse(os.path.join(self._zip_folder, sheet_file))     for cell, value in data.items():         self._change_cell(xml, cell, value)      return etree.tostring(xml, xml_declaration=True, encoding=&quot;UTF-8&quot;, standalone=&quot;yes&quot;) <\/code><\/pre>\n<p>  \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u044f\u0447\u0435\u0439\u043a\u0443, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044f \u043d\u0430 \u0432\u0445\u043e\u0434 \u043b\u0438\u0441\u0442, \u0430\u0434\u0440\u0435\u0441 \u044f\u0447\u0435\u0439\u043a\u0438 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<br \/>  \u0422\u0443\u0442 \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442.<br \/>  \u042f\u0447\u0435\u0439\u043a\u0430 \u0432 XML \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c (\u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u044f\u0447\u0435\u0439\u043a\u0430\u0445).<br \/>  \u042d\u0442\u0430 \u044f\u0447\u0435\u0439\u043a\u0430, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043e\u0442\u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0438 \u0440\u0430\u0441\u043a\u0440\u0430\u0448\u0435\u043d\u0430.<br \/>  \u0414\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0443\u0437\u043b\u0430 \u0441 \u044f\u0447\u0435\u0439\u043a\u043e\u0439.<br \/>  \u0412\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0430\u043c\u043e\u0441\u0442\u043e\u044f\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430\u043b\u0438\u0447\u0438\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0435 <br \/>  \u0438\u043b\u0438 \u0441\u0430\u043c\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0432 \u043a\u043d\u0438\u0433\u0435.  <\/p>\n<pre><code class=\"python\">def _change_cell(self, xml, cell, value):     u&quot;&quot;&quot;      \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u043b\u0438\u0441\u0442\u0435 xml      \u041c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044e \u043a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 xml          @param xml: \u041e\u0431\u044a\u0435\u043a\u0442 lxml     @param cell: \u0418\u043d\u0434\u0435\u043a\u0441 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 &quot;C2&quot;     @param value: \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435     &quot;&quot;&quot;      row_index = self._row_finder.search(cell).group()     value_type = type(value)      pattern_params = {'row_index': row_index, 'cell': cell}     pattern = '\/ws:worksheet\/ws:sheetData\/ws:row[@r=&quot;%(row_index)s&quot;]\/ws:c[@r=&quot;%(cell)s&quot;]' % pattern_params     node_c = xml.xpath(pattern, namespaces=self._namespaces)[0]     node_v = node_c.find('ws:v', namespaces=self._namespaces)          # \u0412 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0431\u044b\u043b\u043e \u043f\u0443\u0441\u0442\u043e - \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0443\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     if node_v is None:         node_v = etree.Element('v')         node_c.append(node_v)      # \u041f\u0443\u0441\u0442\u043e     if value == None:         node_c.remove(node_v)         if node_c.attrib.get('t') == 's':            del node_c.attrib['t']      # \u0420\u0430\u0441\u0448\u0430\u0440\u0435\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430     elif value_type in (unicode, str):         value = str(self._add_shared_string(value))         node_c.attrib['t'] = 's'      # \u0427\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u0438\u043b\u0438 \u043f\u0440\u0438\u0440\u0430\u0432\u043d\u0435\u043d\u043d\u044b\u0435 \u043a \u043d\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435     else:         if node_c.attrib.get('t') == 's':            del node_c.attrib['t']          if value_type == datetime:             value = value.date()          if value_type == date:             value = (value - date(1899, 12, 30)).days      node_v.text = unicode(value) <\/code><\/pre>\n<p>  \u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0432\u0441\u0435\u0433\u043e \u0434\u0432\u0430.<\/p>\n<p>  \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c. \u041d\u0430 \u044d\u0442\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u043d\u0435 \u0432\u043d\u043e\u0441\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<br \/>  \u0421\u044e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445:<br \/>   \u2014 None<br \/>   \u2014 \u0427\u0438\u0441\u043b\u043e (int, float)<br \/>   \u2014 \u0421\u0442\u0440\u043e\u043a\u0430 (str, unicode)<br \/>   \u2014 \u0414\u0430\u0442\u0430  <\/p>\n<pre><code class=\"python\">def write(self, sheet, cell, value):     u&quot;&quot;&quot;      \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0430 \u043b\u0438\u0441\u0442\u0435     \u041d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u044c.     \u041e\u043d\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0430\u0439\u043b-\u0430\u0440\u0445\u0438\u0432\u0430 xlsx          @param sheet: \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043b\u0438\u0441\u0442\u0430     @param cell: \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 C4)     @param value: \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u044f\u0447\u0435\u0439\u043a\u0443     &quot;&quot;&quot;      if value is not None and type(value) not in (int, float, str, unicode):         raise TypeError(u'\u0422\u043e\u043b\u044c\u043a\u043e None, int, float, str, unicode')      if sheet not in self._data:         self._data[sheet] = {}     self._data[sheet][cell] = value <\/code><\/pre>\n<p>  \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0430\u0440\u0445\u0438\u0432\u0430.<br \/>  \u041d\u0435 \u0441\u0442\u0430\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0432 \u0432\u0438\u0434\u0435 \u0444\u0430\u0439\u043b\u0430, zip-\u0430\u0440\u0445\u0438\u0432\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0431\u043e\u043b\u0435\u0435 \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d<br \/>  \u0438 \u0435\u0433\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 HttpResponse  <\/p>\n<pre><code class=\"python\">def get_content(self):     u&quot;&quot;&quot;      \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0444\u0430\u0439\u043b xlsx \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438.      \u041b\u0438\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438, \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c      &quot;&quot;&quot;      exclude_files = ['\/%s' % e[1] for e in self._sheet_paths.items() if e[0] in self._data.keys()]     exclude_files.append('\/xl\/sharedStrings.xml')      zip_file = self._create_base_zip(exclude_files=exclude_files)     self._add_changes(zip_file)      zip_file.writestr('xl\/sharedStrings.xml',                        etree.tostring(self._shared_strings,                                       xml_declaration=True,                                       encoding=&quot;UTF-8&quot;,                                       standalone=&quot;yes&quot;))      zip_file.close()          return self._zip_stream.getvalue() <\/code><\/pre>\n<p>  \u0412\u0440\u043e\u0434\u0435, \u0438 \u0432\u0441\u0435.<br \/>  \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u044d\u0442\u0438\u043c \u0432\u043e\u0442 \u0442\u0430\u043a:  <\/p>\n<pre><code class=\"python\">xlsx = XLSXEdit('path_to_unzip_folder')  xlsx.write('Sheet1', 'A1', 333) xlsx.write('Sheet1', 'A2', 44444) xlsx.write('Sheet1', 'A3', datetime.now()) xlsx.write('Sheet1', 'A4', u'\u0421\u0442\u0440\u043e\u043a\u0430')  with open('\/Users\/dibrovsd\/Desktop\/out.xlsx', 'w') as zip_file:     zip_file.write(xlsx.get_content()) <\/code><\/pre>\n<p>  \u042f \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0443\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<br \/>  \u0438 \u0442\u0443\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u043d\u0435\u0442. \u041f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435, <br \/>  \u0435\u0441\u043b\u0438 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u043e\u043d\u043e \u0432\u0430\u0441 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0432\u043e\u0442 \u0447\u0442\u043e<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\"> import os import re from datetime import datetime, date from StringIO import StringIO from zipfile import ZipFile, ZIP_DEFLATED from lxml import etree   class XLSXEdit(object):     u&quot;&quot;&quot;      \u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 xlsx \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u044f\u043c\u0443\u044e \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u0444\u0430\u0439\u043b\u043e\u0432 xml          \u0417\u0430\u0447\u0435\u043c:     \u042d\u0442\u043e \u0431\u044b\u0432\u0430\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u043c, \u043a\u043e\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441 \u043a\u0443\u0447\u0435\u0439 \u0444\u043e\u0440\u043c\u0443\u043b \u0438 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a, \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432, \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043c\u0435\u0434\u0438\u0430-\u0430\u0440\u0442,      \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, MS query \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a (\u043a\u0442\u043e-\u0442\u043e \u0437\u043d\u0430\u043b excel)     \u0438 \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432 \u043f\u0430\u0440\u0443 \u044f\u0447\u0435\u0435\u043a \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f           \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:     \u041c\u044b \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u043f\u0440\u0430\u0432\u0438\u043c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u0443\u0441\u043a\u0438 XML \u0432\u043d\u0443\u0442\u0440\u0438 \u0438 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0435\u043c \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435     &quot;&quot;&quot;      def __init__(self, zip_folder):         u&quot;&quot;&quot;         @param zip_folder: \u041f\u0443\u0442\u044c \u043a \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438, \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0444\u0430\u0439\u043b xlsx         \u0422\u043e \u0435\u0441\u0442\u044c \u0444\u0430\u0439\u043b '[Content_Types].xml' \u0434\u043e\u043b\u0436\u0435\u043d \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438         &quot;&quot;&quot;         self._zip_folder = zip_folder         self._data = {}         self._zip_stream = StringIO()         self._row_finder = re.compile(r'\\d+$')         self._namespaces = {             'ws': 'http:\/\/schemas.openxmlformats.org\/spreadsheetml\/2006\/main',             'rel': 'http:\/\/schemas.openxmlformats.org\/package\/2006\/relationships'         }          self._sheet_paths = self._get_sheet_locations()                  # \u0421\u043b\u043e\u0432\u0430\u0440\u044c \u0441\u0442\u0440\u043e\u043a         self._shared_strings = None         self._shared_strings_root = None         self._shared_strings_index = None      def write(self, sheet, cell, value):         u&quot;&quot;&quot;          \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u044f\u0447\u0435\u0439\u043a\u0438 \u043d\u0430 \u043b\u0438\u0441\u0442\u0435         \u041d\u0430\u0431\u0438\u0440\u0430\u0435\u0442 \u0432\u0441\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u044c.         \u041e\u043d\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 \u0444\u0430\u0439\u043b-\u0430\u0440\u0445\u0438\u0432\u0430 xlsx                  @param sheet: \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043b\u0438\u0441\u0442\u0430         @param cell: \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 C4)         @param value: \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u044f\u0447\u0435\u0439\u043a\u0443         &quot;&quot;&quot;          if value is not None and type(value) not in (int, float, str, unicode, date, datetime):             raise TypeError(u'\u0422\u043e\u043b\u044c\u043a\u043e None, int, float, str, unicode')          if sheet not in self._data:             self._data[sheet] = {}         self._data[sheet][cell] = value      def get_content(self):         u&quot;&quot;&quot;          \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043e\u043d\u0442\u0435\u043d\u0442 \u0444\u0430\u0439\u043b xlsx \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438.          \u041b\u0438\u0441\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438, \u043d\u0435 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c          &quot;&quot;&quot;          exclude_files = ['\/%s' % e[1] for e in self._sheet_paths.items() if e[0] in self._data.keys()]         exclude_files.append('\/xl\/sharedStrings.xml')          zip_file = self._create_base_zip(exclude_files=exclude_files)         self._add_changes(zip_file)          zip_file.writestr('xl\/sharedStrings.xml',                            etree.tostring(self._shared_strings,                                           xml_declaration=True,                                           encoding=&quot;UTF-8&quot;,                                           standalone=&quot;yes&quot;))          zip_file.close()                  return self._zip_stream.getvalue()      def _get_xml(self, file_path):         u&quot;&quot;&quot;          \u0412\u044b\u0442\u0430\u0449\u0438\u0442\u044c XML-\u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u043f\u0430\u043f\u043a\u0438 \u043f\u043e \u043f\u0443\u0442\u0438          @param file_path: \u041f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0448\u0430\u0431\u043b\u043e\u043d\u0430         &quot;&quot;&quot;         return etree.parse(os.path.join(self._zip_folder, file_path))      def _init_shared_strings(self):         u&quot;&quot;&quot;          \u041b\u0435\u043d\u0438\u0432\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u043e \u0441\u043b\u043e\u0432\u0430\u0440\u0435\u043c \u0441\u0442\u0440\u043e\u043a.         \u041b\u0435\u043d\u0438\u0432\u043e - \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f.         \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 self._add_shared_string         &quot;&quot;&quot;         self._shared_strings = self._get_xml('xl\/sharedStrings.xml')         self._shared_strings_root = self._shared_strings.xpath('\/ws:sst', namespaces=self._namespaces)[0]         self._shared_strings_index = int(self._shared_strings_root.attrib['uniqueCount'])      def _add_shared_string(self, value):         u&quot;&quot;&quot;          \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c sharedStrings         \u041d\u0435 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442, \u0447\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0430 \u0443\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u0442\u0443\u0442 \u0431\u044b\u0442\u044c.         \u041d\u043e \u0438\u0437-\u0437\u0430 \u043c\u0430\u043b\u043e\u0433\u043e \u043a\u043e\u043b-\u0432\u0430 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u043f\u043e\u0444\u0438\u0433\u0443 \u043d\u0430 \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u043d\u0438\u0435 \u0441\u043b\u043e\u0432\u0430\u0440\u044f.         uniqueCount \u0438 Count \u043d\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442 (\u0438 \u0431\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442)          @param value: \u0421\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c         @return: \u0418\u043d\u0434\u0435\u043a\u0441 \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435 sharedStrings         &quot;&quot;&quot;         if self._shared_strings is None:             self._init_shared_strings()          node_t = etree.Element('t')         node_t.text = value          node_si = etree.Element('si')         node_si.append(node_t)          self._shared_strings_root.append(node_si)         self._shared_strings_index += 1          return (self._shared_strings_index - 1)      def _get_sheet_locations(self):         u&quot;&quot;&quot;          \u0423\u0437\u043d\u0430\u0435\u043c \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043b\u0438\u0441\u0442\u044b         @return: \u0421\u043b\u043e\u0432\u0430\u0440\u044c. {\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u043b\u0438\u0441\u0442\u0430: \u043f\u0443\u0442\u044c_\u043a_xml}         &quot;&quot;&quot;                  # \u041a\u043d\u0438\u0433\u0438         sheets_id = {}         workbook_xml = self._get_xml('xl\/workbook.xml')         for sheet_xml in workbook_xml.xpath('\/ws:workbook\/ws:sheets\/ws:sheet', namespaces=self._namespaces):             sheet_name = sheet_xml.attrib['name']             sheet_rid = sheet_xml.attrib['{http:\/\/schemas.openxmlformats.org\/officeDocument\/2006\/relationships}id']             sheets_id[sheet_rid] = sheet_name          # \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432         paths = {}         xml = self._get_xml('xl\/_rels\/workbook.xml.rels')         for node in xml.xpath('\/rel:Relationships\/rel:Relationship', namespaces=self._namespaces):             r_id = node.attrib['Id']             path = os.path.join('xl', node.attrib['Target'])              if r_id in sheets_id:                 sheet_label = sheets_id[r_id]                 paths[sheet_label] = path          return paths          def _create_base_zip(self, exclude_files):         u&quot;&quot;&quot;          \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u0430 \u0432 \u043f\u0430\u043f\u043a\u0435 zip_folder \u0434\u043b\u044f \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.         \u0412 \u043d\u0435\u0433\u043e \u043d\u0435 \u0432\u0445\u043e\u0434\u044f\u0442 \u043b\u0438\u0441\u0442\u044b \u0441 \u0438\u0437\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u044f\u0447\u0435\u0439\u043a\u0430\u043c\u0438.         \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0442\u0443\u0434\u0430 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 _add_changes         @param exclude_files: \u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432         @return: \u043e\u0431\u044a\u0435\u043a\u0442 ZipFile         &quot;&quot;&quot;          zip_file = ZipFile(self._zip_stream, mode='a', compression=ZIP_DEFLATED)          for path, dirs, files in os.walk(self._zip_folder):             rel_path = path[len(self._zip_folder):]                          for file_name in files:                 if rel_path == '':                     zip_name = file_name                 else:                     zip_name = os.path.join(rel_path, file_name)                  if zip_name not in exclude_files:                     zip_file.write(os.path.join(path, file_name), zip_name)          return zip_file      def _add_changes(self, zip_file):         u&quot;&quot;&quot;          \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.         \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c \u0444\u0430\u0439\u043b\u044b \u0438 \u0437\u0430\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u0445 \u0432 zip \u043f\u043e\u0432\u0435\u0440\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e          @param zip_file: \u043e\u0431\u044a\u0435\u043a\u0442 ZipFile \u0431\u0435\u0437 \u043b\u0438\u0441\u0442\u043e\u0432, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0435\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0435 \u044f\u0447\u0435\u0439\u043a\u0438         &quot;&quot;&quot;                  # \u041e\u0431\u0445\u043e\u0434\u0438\u043c \u043b\u0438\u0441\u0442\u044b \u0438 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u043c         for sheet_name, data in self._data.items():             sheet_file = self._sheet_paths[sheet_name]                          sheet_content = self._get_changed_sheet(sheet_file=sheet_file, data=data)             zip_file.writestr(sheet_file, sheet_content)      def _get_changed_sheet(self, sheet_file, data):         u&quot;&quot;&quot;          \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 ZIP-\u0430\u0440\u0445\u0438\u0432          @param sheet_file: \u041f\u0443\u0442\u044c \u043a xml-\u0444\u0430\u0439\u043b\u0443 \u0441 \u043b\u0438\u0441\u0442\u043e\u043c         @param data: \u0421\u043b\u043e\u0432\u0430\u0440\u044c \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438 {cell: value}         @return: xml-\u0441\u0442\u0440\u043e\u043a\u0430 \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u043c \u043b\u0438\u0441\u0442\u043e\u043c         &quot;&quot;&quot;          xml = etree.parse(os.path.join(self._zip_folder, sheet_file))         for cell, value in data.items():             self._change_cell(xml, cell, value)          return etree.tostring(xml, xml_declaration=True, encoding=&quot;UTF-8&quot;, standalone=&quot;yes&quot;)      def _change_cell(self, xml, cell, value):         u&quot;&quot;&quot;          \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u043b\u0438\u0441\u0442\u0435 xml          \u041c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044e \u043a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0443 xml                  @param xml: \u041e\u0431\u044a\u0435\u043a\u0442 lxml         @param cell: \u0418\u043d\u0434\u0435\u043a\u0441 \u044f\u0447\u0435\u0439\u043a\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 &quot;C2&quot;         @param value: \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435         &quot;&quot;&quot;          row_index = self._row_finder.search(cell).group()         value_type = type(value)          pattern_params = {'row_index': row_index, 'cell': cell}         pattern = '\/ws:worksheet\/ws:sheetData\/ws:row[@r=&quot;%(row_index)s&quot;]\/ws:c[@r=&quot;%(cell)s&quot;]' % pattern_params         node_c = xml.xpath(pattern, namespaces=self._namespaces)[0]         node_v = node_c.find('ws:v', namespaces=self._namespaces)                  # \u0412 \u0448\u0430\u0431\u043b\u043e\u043d\u0435 \u0431\u044b\u043b\u043e \u043f\u0443\u0441\u0442\u043e - \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0443\u0434\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435         if node_v is None:             node_v = etree.Element('v')             node_c.append(node_v)          # \u041f\u0443\u0441\u0442\u043e         if value == None:             node_c.remove(node_v)             if node_c.attrib.get('t') == 's':                del node_c.attrib['t']          # \u0420\u0430\u0441\u0448\u0430\u0440\u0435\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430         elif value_type in (unicode, str):             value = str(self._add_shared_string(value))             node_c.attrib['t'] = 's'          # \u0427\u0438\u0441\u043b\u043e\u0432\u044b\u0435 \u0438\u043b\u0438 \u043f\u0440\u0438\u0440\u0430\u0432\u043d\u0435\u043d\u043d\u044b\u0435 \u043a \u043d\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435         else:             if node_c.attrib.get('t') == 's':                del node_c.attrib['t']              if value_type == datetime:                 value = value.date()              if value_type == date:                 value = (value - date(1899, 12, 30)).days          node_v.text = unicode(value)  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 \u0432\u044b \u0442\u0430\u043a\u0438, \u0434\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u0434\u043e \u043a\u043e\u043d\u0446\u0430.     \t<\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/254167\/\"> http:\/\/habrahabr.ru\/post\/254167\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>     \t\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e, \u0445\u0430\u0431\u0440\u043e\u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<p>  \u0420\u0435\u0448\u0438\u043b \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 python \u0441 xlsx.<br \/>  \u0414\u0430, \u044f \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u043f\u0440\u043e \u044d\u0442\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435, \u044f \u043d\u0435 \u0441\u043c\u043e\u0433 \u043d\u0430\u0439\u0442\u0438 \u0433\u043e\u0442\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438.<br \/>  \u041d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u044f\u0447\u0435\u0435\u043a \u0443 \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 xls.<\/p>\n<p>  \u0412\u0441\u0435 \u0431\u044b \u043d\u0438\u0447\u0435\u0433\u043e, \u043d\u043e \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b \u043c\u0430\u043a\u0440\u043e\u0441\u044b, \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0438, \u043e\u0431\u044a\u0435\u043a\u0442\u044b media-art, \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u043c\u043d\u043e\u0433\u043e \u0447\u0435\u0433\u043e \u0435\u0449\u0435.<br \/>  \u041f\u0435\u0440\u0435\u0431\u0440\u0430\u0432 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f (openpyxl, xlutils.copy \u0438 \u043f\u0430\u0440\u0443 \u0434\u0440\u0443\u0433\u0438\u0445), \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043e\u043d\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u0442\u044f\u0442 \u0444\u0430\u0439\u043b.<br \/>  \u0410 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0432\u043e\u0434\u0438\u043b\u0430\u0441\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043a \u0442\u043e\u0447\u0435\u0447\u043d\u043e\u0439 \u043f\u0440\u0430\u0432\u043a\u0435 \u044f\u0447\u0435\u0435\u043a \u0438 \u0447\u0442\u043e\u0431 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043a\u0430\u043a \u0431\u044b\u043b\u043e.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-253954","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/253954","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=253954"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/253954\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=253954"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=253954"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=253954"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}