ArcMap批量出图的设计与实现(三)

代码详解

代码主要包含:

Python部分2个文件,分别为:解析地图文档程序(导出文本、另存地图文档)、导出地图到图片的程序。

  • FastParseMapDocument.py
# -*- coding:utf8 -*-
import os
import arcpy
import sys

reload(sys)
sys.setdefaultencoding('utf8')


def parse_map_doc(doc_dir, doc_name, work_issue_prefix):
    """
    解析mxd文档,用途:
    1.创建工作目录
    2.复制一份文档,作为我们真正使用的(以防对原始文件造成修改或破坏)
    3.遍历目录图层,将各要素居中显示并导出属性、另存mxd文档
    :param doc_dir: 原始mxd文档所在目录
    :param doc_name: 原始mxd文档名称
    :param work_issue_prefix: 工作目录名称(不包含其上各层级目录)前缀
    :return:无
    """
    doc_path = os.path.join(doc_dir, doc_name)
    map_doc = arcpy.mapping.MapDocument(doc_path)
    work_dir = os.path.join(doc_dir, work_issue_prefix)
    if os.path.exists(work_dir):
        os.rmdir(work_dir)
    os.makedirs(work_dir)

    work_doc_name = work_issue_prefix + '_' + doc_name  # 真正使用的mxd
    work_doc_path = os.path.join(doc_dir, work_doc_name)
    if os.path.exists(work_doc_path):
        del work_doc_path
    map_doc.saveACopy(work_doc_path)
    del map_doc

    work_map_doc = arcpy.mapping.MapDocument(work_doc_path)
    data_frames = arcpy.mapping.ListDataFrames(work_map_doc)
    layers = arcpy.mapping.ListLayers(work_map_doc, None, data_frames[0])
    for layer in layers:
        if layer.name != u'RT地产用地':  # 目标图层名
            continue
        else:
            with arcpy.da.SearchCursor(layer, ['FID', 'Shape@', u'文件名称', u'宗地号', u'停尝编号2', u'坐落土地面', u'项目名称', u'项目地址',
                                               u'土地证_房']) as cursor:
                for row in cursor:
                    print u'FID = {0}, 项目地址:{1}'.format(row[0], row[7])
                    feature_values = [doc_name.split('.')[0], row[2],
                                      u'宗地号', row[3],
                                      u'宗地代码', row[4],
                                      u'宗地面积', row[5],
                                      u'所在位置', row[6],
                                      u'用地单位', row[7],
                                      u'用地合同号', row[8]]
                    data_frames[0].panToExtent(row[1].extent)  # 当前要素居中

                    feature_file_name = u'temp_feature_{0}.txt'.format(row[0])  # 保存到文本文件中
                    feature_file_path = os.path.join(work_dir, feature_file_name)
                    feature_file = open(feature_file_path, 'w')
                    for a_feature_value in feature_values:
                        feature_file.write(a_feature_value)
                        feature_file.writelines(u'\n')
                    feature_file.close()

                    a_work_file_name = 'temp_feature_' + str(row[0])
                    a_work_doc_path = os.path.join(work_dir, a_work_file_name + '.mxd')
                    work_map_doc.saveACopy(a_work_doc_path)  # 另存为地图文档
  • FastExportMapDocument.py
# -*- coding:utf8 -*-
import os
import arcpy
import sys

reload(sys)
sys.setdefaultencoding('utf8')


def export_map_doc(doc_dir, work_issue_prefix, resolution=512):
    """
    导出地图文档到JPG图片
    :param doc_dir: 原始mxd文档所在目录
    :param work_issue_prefix: 工作目录名称(不包含其上各层级目录)前缀
    :param resolution: 导出图片的分辨率
    :return:无
    """
    # doc_dir = u'D:\\A1_正在处理\\制图1116'
    work_dir = os.path.join(doc_dir, work_issue_prefix)
    print(u'工作目录: {0}'.format(work_dir))
    mxd_files = list(
        filter(lambda filename: os.path.splitext(filename)[1] == '.mxd',
               os.listdir(work_dir)))  # 遍历目录下的mxd文档
    row_index = 0
    for a_doc_file_path in mxd_files:
        row_index += 1
        print(u'{0}/{1} - 正在导出如下文件至图片: {2}'.format(row_index, len(mxd_files), a_doc_file_path))
        a_doc_file_name = os.path.basename(a_doc_file_path).split('.')[0]
        a_doc_full_path = os.path.join(work_dir, a_doc_file_path)
        a_map_doc = arcpy.mapping.MapDocument(a_doc_full_path)
        picture_element = arcpy.mapping.ListLayoutElements(a_map_doc, u'PICTURE_ELEMENT')[0]
        a_source_image_full_path = os.path.join(work_dir, u'{0}.jpg'.format(a_doc_file_name))  # 替换表格图片
        picture_element.sourceImage = a_source_image_full_path
        arcpy.mapping.ExportToJPEG(a_map_doc, u'e_{0}.jpg'.format(a_doc_file_name), resolution=resolution)
        print(u'{0}/{1} - 成功导出图片: {2}'.format(row_index, len(mxd_files), u'e_{0}.jpg'.format(a_doc_file_name)))
        del a_map_doc
        os.remove(a_doc_full_path)  # 删除过程文件
        del picture_element
        os.remove(a_source_image_full_path)  # 删除过程文件
    print(u'导出完毕!将打开结果目录...')
    cmd_param = u"explorer.exe \"%s\"" % work_dir
    os.system(cmd_param.decode('utf-8').encode('gbk'))

C#部分1个文件,即:通过文本替换xlsx表格中的内容,动态导出为图片(含图片白边裁切)。

  • Program.cs
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Spire.Xls;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;

namespace Text2Picture
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (null == args || 2 > args.Length)
                {
                    throw new Exception("参数有误!");
                }
                if (!Directory.Exists(args[0]))
                {
                    Console.WriteLine(args[0]);
                    throw new Exception("请传入工作目录并确保路径合法!");
                }
                if (!File.Exists(args[1]))
                {
                    Console.WriteLine(args[1]);
                    throw new Exception("请传入表格模板文件完整路径并确保路径合法!");
                }
                var sWorkDir = args[0];
                var sTemplatePath = args[1];
                using (var fsTemplate = File.OpenRead(sTemplatePath))
                {
                    //采用NPOI组件替换xlsx文件的内容并另存
                    IWorkbook pWorkbook = new XSSFWorkbook(fsTemplate);
                    if (null == pWorkbook)
                        throw new Exception("Template File Does Not Exist");

                    var pWorkSheet = pWorkbook.GetSheetAt(0);
                    var lstFileInfo = new DirectoryInfo(sWorkDir).GetFiles("*.txt", SearchOption.TopDirectoryOnly);
                    foreach (var aFileInfo in lstFileInfo)
                    {
                        Console.WriteLine($"----->开始干活: {aFileInfo.Name}");
                        using (var sr = aFileInfo.OpenText())
                        {
                            var sLine = string.Empty;
                            var nLineIndex = 0;
                            var nRowIndex = 0;
                            var nColumnIndex = 0;
                            while (null != (sLine = sr.ReadLine()))
                            {
                                Console.WriteLine($"第{nLineIndex + 1}个(行号{nRowIndex},列号C{nColumnIndex}), 值: {sLine}");
                                nRowIndex = nLineIndex / 2;
                                nColumnIndex = nLineIndex % 2;
                                nLineIndex++;
                                var row = pWorkSheet.GetRow(nRowIndex);
                                if (nRowIndex == 3 && nColumnIndex == 1)
                                {
                                    sLine += "m\x00B2";//平方米,其中目标用unicode编码表示
                                }
                                row.GetCell(nColumnIndex).SetCellValue(sLine);
                            }
                            sr.Close();
                        }

                        var sFilePathNoExt = Path.Combine(sWorkDir, aFileInfo.Name.Split('.')[0]);
                        var sNewFilePath = sFilePathNoExt + ".xlsx";
                        Console.WriteLine($"保存文件: {sNewFilePath}");
                        using (var sNewFileStream = new FileStream(sNewFilePath, FileMode.Create))
                        {
                            pWorkbook.Write(sNewFileStream);
                            sNewFileStream.Close();
                        }

                        //采用Spire.XLS组件将xlsx特定区域导出为图片
                        Workbook workbook = new Workbook();
                        workbook.LoadFromFile(sNewFilePath);
                        var worksheet = workbook.Worksheets[0];
                        worksheet.AllocatedRange["A1:B7"].AutoFitRows();
                        var image = worksheet.ToImage(0, 0, 7, 2);
                        var newImage = ClipImage(new Bitmap(image));
                        newImage.Save((sFilePathNoExt + ".jpg"));
                        Console.WriteLine($"导出图片: {sFilePathNoExt}.jpg");
                        File.Delete(aFileInfo.FullName);
                        File.Delete(sNewFilePath);
                        Console.WriteLine("完结撒花!<-----");
                    }
                    fsTemplate.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.WriteLine("0");
            }
        }

        /// <summary>
        /// 裁剪图片
        /// 使用默认导出的文件,上下左右各有约65像素的白边,
        /// 导入到地图文档中时,会遮盖地图,影响布局,
        /// 因此,在导出xlsx特定区域到图片文件前,先裁切白边
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="nBorderSize"></param>
        /// <returns></returns>
        private static Image ClipImage(Bitmap bmp, int nBorderSize = 65)
        {
            Bitmap newBmp = null;
            if (bmp.Height > 2 * nBorderSize && bmp.Width > 2 * nBorderSize)
            {
                newBmp = new Bitmap(bmp.Width - 2 * nBorderSize, bmp.Height - 2 * nBorderSize);
                var g = Graphics.FromImage(newBmp);
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.DrawImage(bmp,
                    new Rectangle(0, 0, bmp.Width - 2 * nBorderSize, bmp.Height - 2 * nBorderSize),
                    new Rectangle(nBorderSize, nBorderSize, bmp.Width - 2 * nBorderSize, bmp.Height - 2 * nBorderSize),
                    GraphicsUnit.Pixel);
                g.Dispose();
            }
            return newBmp;
        }
    }
}

程序封装

采用一个Python文件,通过少量几行代码,实现对Python代码、C#编译的可执行文件的调用。

  • Startup.py
# -*- coding:utf8 -*-
import os
import time
import sys
import arcpy

import FastParseMapDocument
import FastExportMapDocument

reload(sys)
sys.setdefaultencoding('utf8')

if __name__ == '__main__':
    mxd_full_path = u'{0}'.format(sys.argv[1].decode('gbk').encode('utf-8'))
    arcpy.AddMessage(u'输入的mxd文档路径为: {0}'.format(mxd_full_path))
    doc_dir = os.path.dirname(mxd_full_path)
    doc_name = os.path.basename(mxd_full_path)
    work_issue_prefix = 'T' + time.strftime("%Y%m%d%H%M%S", time.localtime())
    exe_bin_dir = os.path.join(os.path.abspath(os.curdir), u'bin')
    # exe_bin_dir = u'D:\\A15_Test\\FastExportMxd\\bin'
    template_xlsx_path = os.path.join(exe_bin_dir, u'data_template.xlsx')
    bat_file_path = os.path.join(exe_bin_dir, u'temp.bat')
    FastParseMapDocument.parse_map_doc(doc_dir, doc_name, work_issue_prefix)
    cmd_param = u"%s \"%s\" \"%s\"" % (bat_file_path, os.path.join(doc_dir, work_issue_prefix), template_xlsx_path)
    process_cmd = os.popen(cmd_param.decode('utf-8').encode('gbk'))
    print process_cmd.read()
    process_cmd.close()
    FastExportMapDocument.export_map_doc(doc_dir, work_issue_prefix)
  • temp.bat
set current_path=%~dp0
start %current_path%\Text2Picture.exe %1 %2

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值