def coordinate(self, idx):
        """
        Return coordinate of cell area ordered starting from top_left going clockwise.
        :param idx: 0,1,2,3 and 4 for CENTER
        :return:
        """
        if not isinstance(idx, int):
            raise TypeError
        row_idx, col_idx = self._parent.cell_idx(self)
        tbl = self._tc.getparent().getparent()
        # table is inside graphic frame. Graphic frame is a thing that's inside slide.
        gf = tbl.getparent().getparent().getparent()
        top_left = [gf.x, gf.y]
        for tr in tbl.tr_lst[:row_idx]:
            top_left[1] += tr.h
        for gc in tbl.tblGrid.gridCol_lst[:col_idx]:
            top_left[0] += gc.w

        if idx == 0:
            return Emu(top_left[0]), Emu(top_left[1])
        elif idx == 1:
            return Emu(top_left[0] + self.width), Emu(top_left[1])
        elif idx == 2:
            return Emu(top_left[0]) + self.width, Emu(top_left[1] +
                                                      self.height)
        elif idx == 3:
            return Emu(top_left[0]), Emu(top_left[1] + self.height)
        elif idx == 4:
            return Emu(top_left[0] + self.width / 2), Emu(top_left[1] +
                                                          self.height / 2)
        else:
            raise ValueError
def when_I_call_shapes_add_movie(context):
    shapes = context.shapes
    x, y, cx, cy = Emu(2590800), Emu(571500), Emu(3962400), Emu(5715000)
    context.movie = shapes.add_movie(
        test_file('just-two-mice.mp4'), x, y, cx, cy,
        test_file('just-two-mice.png')
    )
Beispiel #3
0
 def _get_marX(self, attr_name, default):
     """
     Generalized method to get margin values.
     """
     if self.tcPr is None:
         return Emu(default)
     return Emu(int(self.tcPr.get(attr_name, default)))
Beispiel #4
0
def when_I_assign_value_to_paragraph_line_spacing(context, value_str):
    value = {
        '1.5':    1.5,
        '2.0':    2.0,
        '254000': Emu(254000),
        '304800': Emu(304800),
        'None':   None,
    }[value_str]
    paragraph = context.paragraph
    paragraph.line_spacing = value
Beispiel #5
0
    def _cy(self):
        """Emu object specifying height of "show-as-icon" image for OLE shape."""
        # --- a user-specified width overrides any default ---
        if self._cy_arg is not None:
            return self._cy_arg

        # --- the default height is specified by the PROG_ID member if prog_id is one,
        # --- otherwise it gets the default icon height.
        return (Emu(self._prog_id_arg.height)
                if self._prog_id_arg in PROG_ID else Emu(609600))
Beispiel #6
0
def when_I_assign_value_to_paragraph_line_spacing(context, value_str):
    value = {
        "1.5": 1.5,
        "2.0": 2.0,
        "254000": Emu(254000),
        "304800": Emu(304800),
        "None": None,
    }[value_str]
    paragraph = context.paragraph
    paragraph.line_spacing = value
Beispiel #7
0
    def _cx(self):
        """Emu object specifying width of "show-as-icon" image for OLE shape."""
        # --- a user-specified width overrides any default ---
        if self._cx_arg is not None:
            return self._cx_arg

        # --- the default width is specified by the PROG_ID member if prog_id is one,
        # --- otherwise it gets the default icon width.
        return (Emu(self._prog_id_arg.width)
                if self._prog_id_arg in PROG_ID else Emu(965200))
Beispiel #8
0
def add_slide_to_ppt(ppt, image):
    """
        append an slide to the presentation with
        the image
    """
    size = (Emu(ppt.slide_width).pt, Emu(ppt.slide_height).pt)
    blank_slide_layout = ppt.slide_layouts[6]
    left = top = Emu(0)
    slide = ppt.slides.add_slide(blank_slide_layout)

    image = resize_patch_image(image, size)

    logging.info("adding image to presentation, slides: [{}]".format(
        len(ppt.slides)))
    pic = slide.shapes.add_picture(image, left, top)
Beispiel #9
0
 def cy(self):
     """
     Shape height as an instance of Emu, or None if not present.
     """
     cy_str_lst = self.xpath("./a:xfrm/a:ext/@cy")
     if not cy_str_lst:
         return None
     return Emu(cy_str_lst[0])
Beispiel #10
0
 def cx(self):
     """
     Shape width as an instance of Emu, or None if not present.
     """
     cx_str_lst = self.xpath("./a:xfrm/a:ext/@cx")
     if not cx_str_lst:
         return None
     return Emu(cx_str_lst[0])
Beispiel #11
0
    def add_image_slide(self, image_downloaded):
        image_layout = self.presentation.slide_layouts[SLD_LAYOUT_IMAGE]
        slide = self.presentation.slides.add_slide(image_layout)

        picture = self.picture_fitted(slide, image_downloaded)

        pos_x = (self.presentation.slide_width.inches - Emu(picture.width).inches) / 2
        picture.left = Inches(pos_x).emu
Beispiel #12
0
 def convert_from_xml(cls, str_value):
     float_part, units_part = str_value[:-2], str_value[-2:]
     quantity = float(float_part)
     multiplier = {
         'mm': 36000, 'cm': 360000, 'in': 914400, 'pt': 12700,
         'pc': 152400, 'pi': 152400
     }[units_part]
     emu_value = Emu(int(round(quantity * multiplier)))
     return emu_value
Beispiel #13
0
 def begin_x(self):
     """
     Return the X-position of the begin point of this connector, in
     English Metric Units (as a |Length| object).
     """
     cxnSp = self._element
     x, cx, flipH = cxnSp.x, cxnSp.cx, cxnSp.flipH
     begin_x = x + cx if flipH else x
     return Emu(begin_x)
Beispiel #14
0
 def y(self):
     """
     The offset of the top of the shape from the top of the slide, as an
     instance of Emu. None if not present.
     """
     y_str_lst = self.xpath("./a:xfrm/a:off/@y")
     if not y_str_lst:
         return None
     return Emu(y_str_lst[0])
Beispiel #15
0
 def begin_y(self):
     """
     Return the Y-position of the begin point of this connector, in
     English Metric Units (as a |Length| object).
     """
     cxnSp = self._element
     y, cy, flipV = cxnSp.y, cxnSp.cy, cxnSp.flipV
     begin_y = y + cy if flipV else y
     return Emu(begin_y)
Beispiel #16
0
class CT_TextBodyProperties(BaseOxmlElement):
    """
    <a:bodyPr> custom element class
    """

    eg_textAutoFit = ZeroOrOneChoice(
        (Choice("a:noAutofit"), Choice("a:normAutofit"),
         Choice("a:spAutoFit")),
        successors=("a:scene3d", "a:sp3d", "a:flatTx", "a:extLst"),
    )
    lIns = OptionalAttribute("lIns", ST_Coordinate32, default=Emu(91440))
    tIns = OptionalAttribute("tIns", ST_Coordinate32, default=Emu(45720))
    rIns = OptionalAttribute("rIns", ST_Coordinate32, default=Emu(91440))
    bIns = OptionalAttribute("bIns", ST_Coordinate32, default=Emu(45720))
    anchor = OptionalAttribute("anchor", MSO_VERTICAL_ANCHOR)
    wrap = OptionalAttribute("wrap", ST_TextWrappingType)

    @property
    def autofit(self):
        """
        The autofit setting for the text frame, a member of the
        ``MSO_AUTO_SIZE`` enumeration.
        """
        if self.noAutofit is not None:
            return MSO_AUTO_SIZE.NONE
        if self.normAutofit is not None:
            return MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE
        if self.spAutoFit is not None:
            return MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT
        return None

    @autofit.setter
    def autofit(self, value):
        if value is not None and value not in MSO_AUTO_SIZE._valid_settings:
            raise ValueError(
                "only None or a member of the MSO_AUTO_SIZE enumeration can "
                "be assigned to CT_TextBodyProperties.autofit, got %s" % value)
        self._remove_eg_textAutoFit()
        if value == MSO_AUTO_SIZE.NONE:
            self._add_noAutofit()
        elif value == MSO_AUTO_SIZE.TEXT_TO_FIT_SHAPE:
            self._add_normAutofit()
        elif value == MSO_AUTO_SIZE.SHAPE_TO_FIT_TEXT:
            self._add_spAutoFit()
Beispiel #17
0
 def x(self):
     """
     The offset of the left edge of the shape from the left edge of the
     slide, as an instance of Emu. Corresponds to the value of the
     `./xfrm/off/@x` attribute. None if not present.
     """
     x_str_lst = self.xpath("./a:xfrm/a:off/@x")
     if not x_str_lst:
         return None
     return Emu(x_str_lst[0])
Beispiel #18
0
 def _new_placeholder_table(self, rows, cols):
     """
     Return a newly added `p:graphicFrame` element containing an empty
     table with *rows* rows and *cols* columns, positioned at the location
     of this placeholder and having its same width. The table's height is
     determined by the number of rows.
     """
     shape_id, name, height = self.shape_id, self.name, Emu(rows * 370840)
     return CT_GraphicalObjectFrame.new_table_graphicFrame(
         shape_id, name, rows, cols, self.left, self.top, self.width,
         height)
Beispiel #19
0
class CT_LineProperties(BaseOxmlElement):
    """Custom element class for <a:ln> element"""

    _tag_seq = (
        "a:noFill",
        "a:solidFill",
        "a:gradFill",
        "a:pattFill",
        "a:prstDash",
        "a:custDash",
        "a:round",
        "a:bevel",
        "a:miter",
        "a:headEnd",
        "a:tailEnd",
        "a:extLst",
    )
    eg_lineFillProperties = ZeroOrOneChoice(
        (
            Choice("a:noFill"),
            Choice("a:solidFill"),
            Choice("a:gradFill"),
            Choice("a:pattFill"),
        ),
        successors=_tag_seq[4:],
    )
    prstDash = ZeroOrOne("a:prstDash", successors=_tag_seq[5:])
    custDash = ZeroOrOne("a:custDash", successors=_tag_seq[6:])
    del _tag_seq
    w = OptionalAttribute("w", ST_LineWidth, default=Emu(0))

    @property
    def eg_fillProperties(self):
        """
        Required to fulfill the interface used by dml.fill.
        """
        return self.eg_lineFillProperties

    @property
    def prstDash_val(self):
        """Return value of `val` attribute of `a:prstDash` child.

        Return |None| if not present.
        """
        prstDash = self.prstDash
        if prstDash is None:
            return None
        return prstDash.val

    @prstDash_val.setter
    def prstDash_val(self, val):
        self._remove_custDash()
        prstDash = self.get_or_add_prstDash()
        prstDash.val = val
Beispiel #20
0
    def _child_extents(self):
        """(x, y, cx, cy) tuple representing net position and size.

        The values are formed as a composite of the contained child shapes.
        """
        child_shape_elms = list(self.iter_shape_elms())

        if not child_shape_elms:
            return Emu(0), Emu(0), Emu(0), Emu(0)

        min_x = min([xSp.x for xSp in child_shape_elms])
        min_y = min([xSp.y for xSp in child_shape_elms])
        max_x = max([(xSp.x + xSp.cx) for xSp in child_shape_elms])
        max_y = max([(xSp.y + xSp.cy) for xSp in child_shape_elms])

        x = min_x
        y = min_y
        cx = max_x - min_x
        cy = max_y - min_y

        return x, y, cx, cy
Beispiel #21
0
    def orient(self, x, y, ref_idx=0):
        """
        Change position of shape by placing vertex[ref_idx] to position x,y
        :param x: destination x
        :param y: destination y
        :param ref_idx: reference vertex to move with
        :return:
        """
        if not isinstance(ref_idx, int):
            raise TypeError
        if not isinstance(x, Length) or not isinstance(y, Length):
            raise TypeError

        if ref_idx == 0:
            self._element.x = x
            self._element.y = y
        elif ref_idx == 1:
            self._element.x = Emu(x - self._element.cx)
        elif ref_idx == 2:
            self._element.x = Emu(x - self._element.cx)
            self._element.y = Emu(y - self._element.cy)
        elif ref_idx == 3:
            self._element.y = Emu(y - self._element.cy)
        elif ref_idx == 4:
            self._element.x = Emu(x - self._element.cx / 2)
            self._element.y = Emu(y - self._element.cy / 2)
        else:
            raise ValueError
Beispiel #22
0
 def convert_from_xml(cls, str_value):
     float_part, units_part = str_value[:-2], str_value[-2:]
     quantity = float(float_part)
     multiplier = {
         "mm": 36000,
         "cm": 360000,
         "in": 914400,
         "pt": 12700,
         "pc": 152400,
         "pi": 152400,
     }[units_part]
     emu_value = Emu(int(round(quantity * multiplier)))
     return emu_value
Beispiel #23
0
    def coordinate(self, idx):
        if not isinstance(idx, int):
            raise TypeError

        top_left = [self._element.x, self._element.y]
        w, h = self._element.cx, self._element.cy

        if idx == 0:
            return tuple(top_left)
        elif idx == 1:
            return Emu(top_left[0] + w), Emu(top_left[1])
        elif idx == 2:
            return Emu(top_left[0] + w), Emu(top_left[1] + h)
        elif idx == 3:
            return Emu(top_left[0]), Emu(top_left[1] + h)
        elif idx == 4:
            return Emu(top_left[0] + w / 2), Emu(top_left[1] + h / 2)
        else:
            raise ValueError
Beispiel #24
0
 def convert_to_xml(cls, value):
     length = Emu(value)  # just to make sure
     return str(length.centipoints)
Beispiel #25
0
 def convert_from_xml(cls, str_value):
     return Emu(str_value)
Beispiel #26
0
 def convert_from_xml(cls, str_value):
     int_value = super(ST_PositiveCoordinate,
                       cls).convert_from_xml(str_value)
     return Emu(int_value)
Beispiel #27
0
 def convert_from_xml(cls, str_value):
     if "i" in str_value or "m" in str_value or "p" in str_value:
         return ST_UniversalMeasure.convert_from_xml(str_value)
     return Emu(int(str_value))
Beispiel #28
0
def plot_chart(prs,df,chart_type,title=u'我是标题',summary=u'我是简短的结论',\
footnote=None,chart_format=None,layouts=[0,0],has_data_labels=True):
    '''
    直接将数据绘制到一张ppt上,且高度定制化
    默认都有图例,且图例在下方
    默认都有数据标签
    '''

    slide_width = prs.slide_width
    slide_height = prs.slide_height
    # 可能需要修改以适应更多的情形
    # layouts[0]代表第几个母版,layouts[1]代表母版中的第几个版式
    title_only_slide = prs.slide_masters[layouts[0]].slide_layouts[layouts[1]]
    slide = prs.slides.add_slide(title_only_slide)
    # 添加标题 title=u'这里是标题'
    try:
        slide.shapes.title.text = title
    except:
        print('请检查模板,脚本没有找到合适的slide')
        return
    # 添加结论 summary=u'这里是一些简短的结论'
    #summary_loc=[0.10,0.14,0.80,0.15]
    left, top = Emu(config.summary_loc[0] * slide_width), Emu(
        config.summary_loc[1] * slide_height)
    width, height = Emu(config.summary_loc[2] * slide_width), Emu(
        config.summary_loc[3] * slide_height)
    txBox = slide.shapes.add_textbox(left, top, width, height)
    txBox.text_frame.text = summary
    txBox.text_frame.paragraphs[0].font.language_id = 3076
    try:
        txBox.text_frame.fit_text(max_size=12)
    except:
        pass
        #print('cannot fit the size of font')

    # 添加脚注 footnote=u'这里是脚注'
    if footnote:
        left, top = Emu(0.025 * slide_width), Emu(0.95 * slide_height)
        width, height = Emu(0.70 * slide_width), Emu(0.10 * slide_height)
        txBox = slide.shapes.add_textbox(left, top, width, height)
        #p = text_frame.paragraphs[0]
        p = txBox.text_frame.paragraphs[0]
        p.text = footnote
        p.font.size = Pt(10)
        p.font.language_id = 3076
        p.font.name = 'Microsoft YaHei UI'
        p.font.color.rgb = RGBColor(127, 127, 127)
        try:
            txBox.text_frame.fit_text(max_size=10)
        except:
            pass
            #print('cannot fit the size of font')

    # 插入图表
    chart_type_code = chart_list[chart_type][1]
    chart_data = df_to_chartdata(df, chart_type_code)
    #left, top = Emu(0.05*slide_width), Emu(0.20*slide_height)
    #width, height = Emu(0.85*slide_width), Emu(0.70*slide_height)
    #chart_loc=[0.10,0.30,0.80,0.60]
    left, top = Emu(config.chart_loc[0] * slide_width), Emu(
        config.chart_loc[1] * slide_height)
    width, height = Emu(config.chart_loc[2] * slide_width), Emu(
        config.chart_loc[3] * slide_height)

    chart=slide.shapes.add_chart(chart_list[chart_type.upper()][0], \
    left, top, width, height, chart_data).chart

    if chart_type_code in [-4169, 72, 73, 74, 75]:
        return

    font_default_size = Pt(10)
    # 添加图例
    if (df.shape[1] > 1) or (chart_type == 'PIE'):
        chart.has_legend = True
        chart.legend.font.size = font_default_size
        chart.legend.position = XL_LEGEND_POSITION.BOTTOM
        chart.legend.include_in_layout = False

    try:
        chart.category_axis.tick_labels.font.size = font_default_size
    except:
        pass  #暂时不知道怎么处理
    try:
        chart.value_axis.tick_labels.font.size = font_default_size
    except:
        pass
    # 添加数据标签

    non_available_list=['BUBBLE','BUBBLE_THREE_D_EFFECT','XY_SCATTER',\
    'XY_SCATTER_LINES','PIE']
    # 大致检测是否采用百分比
    # 1、单选题每列的和肯定是100,顶多相差+-5
    # 2、多选题每一列的和大于100,但单个的小于100.此处可能会有误判,但暂时无解
    # 3、可能会有某一列全为0,此时单独考虑
    if ((df.sum()[df.sum() != 0] > 90).all()) and (
        (df <= 100).all().all()) and (u'总体' not in df.index):
        # 数据条的数据标签格式
        #number_format1='0.0"%"'
        number_format1 = config.number_format_data
        # 坐标轴的数据标签格式
        #number_format2='0"%"'
        number_format2 = config.number_format_tick
    else:
        number_format1 = '0.00'
        number_format2 = '0.0'

    if (chart_type not in non_available_list) or (chart_type == 'PIE'):
        plot = chart.plots[0]
        plot.has_data_labels = True
        plot.data_labels.font.size = font_default_size
        plot.data_labels.number_format = number_format1
        #plot.data_labels.number_format_is_linked=True
        #data_labels = plot.data_labels
        #plot.data_labels.position = XL_LABEL_POSITION.BEST_FIT
    if (chart_type not in non_available_list):
        #chart.value_axis.maximum_scale = 1
        if df.shape[1] == 1:
            chart.value_axis.has_major_gridlines = False
        else:
            chart.value_axis.has_major_gridlines = True
        tick_labels = chart.value_axis.tick_labels
        tick_labels.number_format = number_format2
        tick_labels.font.size = font_default_size

    # 修改纵坐标格式
    '''
    tick_labels = chart.value_axis.tick_labels
    tick_labels.number_format = '0"%"'
    tick_labels.font.bold = True
    tick_labels.font.size = Pt(10)
    '''

    # 填充系列的颜色
    ''' 最好的方法还是修改母版文件中的主题颜色,这里只提供方法
    if df.shape[1]==1:
        chart.series[0].fill()
    '''

    # 自定义format
    if chart_format:
        for k in chart_format:
            exec('chart.' + k + '=' + '%s' % (chart_format[k]))

    return prs
    '''
Beispiel #29
0
def plot_cover(prs,
               title=u'reportgen工具包封面',
               layouts=[0, 0],
               xspace=8,
               yspace=6):

    slide_width = prs.slide_width
    slide_height = prs.slide_height
    # 可能需要修改以适应更多的情形
    title_only_slide = prs.slide_masters[layouts[0]].slide_layouts[layouts[1]]
    slide = prs.slides.add_slide(title_only_slide)

    ## 随机生成连接点
    seeds = np.round(
        np.dot(np.random.rand((xspace - 1) * (yspace - 1), 2),
               np.diag([slide_width, slide_height])))
    # 添加左边点
    tmp = np.linspace(0, slide_height, yspace)
    seeds = np.concatenate((seeds, np.array([[0] * len(tmp), tmp]).T))
    # 添加上边点
    tmp = np.linspace(0, slide_width, xspace)[1:]
    seeds = np.concatenate((seeds, np.array([tmp, [0] * len(tmp)]).T))
    # 添加右边点
    tmp = np.linspace(0, slide_height, yspace)[1:]
    seeds = np.concatenate((seeds, np.array([[slide_width] * len(tmp),
                                             tmp]).T))
    # 添加下边点
    tmp = np.linspace(0, slide_width, xspace)[1:-1]
    seeds = np.concatenate((seeds, np.array([tmp,
                                             [slide_height] * len(tmp)]).T))

    # 构造三角剖分,生成相应的三角形和平面图数据
    center = np.mean(seeds, axis=0)
    t = np.sqrt(slide_width**2 + slide_height**2) / 2
    dt = Delaunay2D(center, 2**(np.floor(np.log2(t)) + 1))
    for s in seeds:
        dt.AddPoint(s)
    tri = dt.exportTriangles()
    graph = np.zeros((len(seeds), len(seeds)))
    for t in tri:
        graph[t[0], t[1]] = 1
        graph[t[1], t[2]] = 1
        graph[t[0], t[2]] = 1
        graph[t[1], t[0]] = 1
        graph[t[2], t[1]] = 1
        graph[t[2], t[1]] = 1

    from pptx.enum.shapes import MSO_CONNECTOR
    from pptx.enum.shapes import MSO_SHAPE
    shapes = slide.shapes
    # 添加连接线
    for i in range(len(seeds)):
        for j in range(len(seeds)):
            if (i < j) and graph[i, j] == 1:
                shapes.add_connector(MSO_CONNECTOR.STRAIGHT, Emu(seeds[i, 0]),
                                     Emu(seeds[i, 1]), Emu(seeds[j, 0]),
                                     Emu(seeds[j, 1]))
    # 添加圆点,原点的半径符合高斯分布
    radius = slide_width / 100
    for i in range(len(seeds)):
        eps = np.random.normal(scale=radius * 0.2)
        left = Emu(seeds[i, 0]) - radius - eps
        top = Emu(seeds[i, 1]) - radius - eps
        width = height = 2 * (radius + eps)
        shape = shapes.add_shape(MSO_SHAPE.OVAL, left, top, width, height)
        shape.line.width = Emu(0)
        fill = shape.fill
        fill.solid()
        fill.fore_color.rgb = RGBColor(218, 227, 243)

    # 添加标题
    left, top = Emu(0), Emu(0.4 * slide_height)
    width, height = Emu(1 * slide_width), Emu(0.2 * slide_height)
    shape = shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
    shape.line.width = Emu(0)
    fill = shape.fill
    fill.solid()
    fill.fore_color.rgb = RGBColor(0, 176, 240)
    shape.text = title

    # 添加脚注
    left, top = Emu(0.72 * slide_width), Emu(0.93 * slide_height)
    width, height = Emu(0.25 * slide_width), Emu(0.07 * slide_height)
    txBox = slide.shapes.add_textbox(left, top, width, height)
    txBox.text_frame.text = 'POWERED BY REPORTGEN'

    # 添加LOGO
    logo_path = os.path.join(_thisdir, 'images', 'logo.png')
    if os.path.exists(logo_path):
        left, top = Emu(0.65 * slide_width), Emu(0.94 * slide_height)
        height = Emu(0.06 * slide_height)
        slide.shapes.add_picture(logo_path, left, top, height=height)
    return prs
Beispiel #30
0
    def location_suggest(self, num=1, rate=0.78, data=None, summary=None):
        '''统一管理slides各个模块的位置
        parameter
        --------
        num: 主体内容(如图、外链图片、文本框等)的个数,默认从左到右依次排列
        rate: 主体内容的宽度综合
        data: list,通过数据类型智能判断位置,如有,则 num 失效
        summary:如果summary为空,则非图表等位置都会上移动

        return
        -----
        locations: dict格式. l代表left,t代表top,w代表width,h代表height
        '''
        slide_width, slide_height = self.prs.slide_width, self.prs.slide_height
        if 'summary_loc' in config.__dict__:
            summary_loc = config.summary_loc
        else:
            summary_loc = [0.10, 0.14, 0.80, 0.15]

        if 'footnote_loc' in config.__dict__:
            footnote_loc = config.footnote_loc
        else:
            footnote_loc = [0.025, 0.95, 0.70, 0.06]

        if 'data_loc' in config.__dict__:
            data_loc = config.data_loc
        else:
            data_loc = [0.11, 0.30, 0.78, 0.60]

        num = len(data) if isinstance(data, list) else num
        locations = {}
        locations['summary']={'l':Emu(summary_loc[0]*slide_width),'t':Emu(summary_loc[1]*slide_height),\
                 'w':Emu(summary_loc[2]*slide_width),'h':Emu(summary_loc[3]*slide_height)}

        locations['footnote']={'l':Emu(footnote_loc[0]*slide_width),'t':Emu(footnote_loc[1]*slide_height),\
                 'w':Emu(footnote_loc[2]*slide_width),'h':Emu(footnote_loc[3]*slide_height)}
        # 主体部分只有一个的情形
        '''
        控制主体的宽度为78%,且居中显示。
        '''
        if (summary is not None) and len(summary) == 0:
            data_loc[1] = data_loc[1] * 0.84
        if num > 1:
            left = [
                (1 - rate) * (i + 1) / (float(num) + 1) + rate * i / float(num)
                for i in range(num)
            ]
            top = [data_loc[1]] * num
            width = [rate / float(num)] * num
            height = [data_loc[3]] * num
            locations['data']=[{'l':Emu(left[i]*slide_width),'t':Emu(top[i]*slide_height),\
                     'w':Emu(width[i]*slide_width),'h':Emu(height[i]*slide_height)} for i in range(num)]
        else:
            # 暂时只修正单张图片常常不居中的问题,后期会修正多张图片
            if data[0]['slide_type'] == 'picture':
                imgdata = mpimg.imread(data[0]['data'])
                img_height, img_width = imgdata.shape[:2]
                img_width_in_pptx = data_loc[
                    3] * slide_height * img_width / img_height / slide_width
                data_loc[0] = 0.5 - img_width_in_pptx / 2

            locations['data']=[{'l':Emu(data_loc[0]*slide_width),'t':Emu(data_loc[1]*slide_height),\
                     'w':Emu(data_loc[2]*slide_width),'h':Emu(data_loc[3]*slide_height)}]

        return locations