3

Is there a way to use Map Packaging so that multiple mxds draw data from the same geodatabase when unpacked? We've broken our project area into 14 divisions. Each division has it's own geodatabase and there are about 30 mxds per division drawing data from that geodatabase. I've been asked to give all our project data (over 400 mxds) to clients and I want to do that efficiently from a file storage standpoint?

In my limited experience with map packaging, it looks like it would create one geodatabase file for every MXD. If true, I'd have over 400 .MPK with each one having it's own geodatabase. Is there a way to reduce the redundancy in geodatabases since there are about 30 mxds pulling data from the same .gdb?

If file duplication and storage is a concern, would it be better to abandon map packages and provide the mxds and data using relative paths?

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Bernie
  • 73
  • 7
  • I suspect you also want to include layouts and such, but if you can skip that for some of them you should also consider using .lyr-files. I'm leaning towards it's easier to go with relative paths, but I'll leave the answering to someone with good arguments. MPK-files are supposed to be self-contained, that's their raison d'être, so I doubt you can create any synergies storage-wise between map packages. – Martin Aug 27 '15 at 13:02

3 Answers3

4

A Map Package (mpk) will only hold 1 MXD, but could hold multiple GDBs. If your original MXD has 100 featureclasses from 5 different databases (multiple fGDB or SDE instances), the data that gets copied to the package will be held inside 5 GDBs named based on the original database. So to your point, you're sort of correct. Its more you'd have 400 MPKs if you had 400 MXDs.

If you want to cut down on the number of MPKs, you'll need to cut down the number of MXDs. You'd have to go through the process of merging MXDs into one (or just a few) master MXDs and packaging those. You could maybe use dataframes as an indicator of what was an MXD. When you package the master MXDs into an MPK, data inside is not duplicated. If a layer existed in multiple dataframe all pointing at the same source, you only get 1 copy of it in the MXD (unless it came from a different database...)

If you have ArcGIS Pro, you could make a PPKX (package project). You'd import all your MXDs into the project, then package the project itself. Of course your client would need ArcGIS Pro.

KHibma
  • 16,786
  • 1
  • 31
  • 55
  • While you're last suggestion looks promising, I'm working in ArcMAP v. 10.1. I'm also stuck with the 400+ mxds. – Bernie Aug 27 '15 at 15:26
  • 1
    I realize my comments above may not provide a "solution", hopefully it provides at least a starting point to help you chose a direction. You'll probably end up writing some script to help merge multiple MXDs OR create multiple packages. Based on what you want today and what you already have, theres no simple way to get to the end. – KHibma Aug 27 '15 at 16:06
0

Map packages are just zip files with a different extension. Use 7zip or whatever to unpack the package somewhere, delete the internal .gdb that hold the in-common data across all MXD, then repack the package.

When the MPK is delivered and opened the MXD will have broken layers; use the standard "Repair data sources" tools/methods to point to the shared in-common data GDB.

The "repair data sources" part can be scripted done before the projects are re-packed and delivered.

Command line example to remove all occurrencess of the shared data (common.gdb) from a map package and repack automatically (ref):

7z d -r repack-example.mpk common.gdb

Script examples for changing layer paths can be seen at Changing data source for all layers in MXD?

matt wilkie
  • 28,176
  • 35
  • 147
  • 280
0

Seven years old but in case anyone is looking for an solution.. I wanted to be able to do this, and the ridiculous data structures created by the map packaging process just didn't cut it for me so I did my normal hacking and chopping of Midalvo's script and came up with the following:

import arcpy, os, datetime
arcpy.env.overwriteOutput = True

folderPath = arcpy.GetParameterAsText(0) newBasePath = arcpy.GetParameterAsText(1) OutFGDBName = arcpy.GetParameterAsText(2) OutFGDBName = OutFGDBName + ".gdb"

newPath = newBasePath # Create new folder for MXD and FGDB newFGDB = str(newPath)+"\" +OutFGDBName if not os.path.isdir(newFGDB): newFGDB = arcpy.CreateFileGDB_management(newPath, OutFGDBName) # Create new FGDB newFGDB = str(newFGDB)

#Loop through each MXD file for root, dirs, files in os.walk(folderPath): for file in files: # files is a list of files in the current directory if file.lower().endswith(".mxd"): dataSourceSet = set() # Keep track of already copied datasources

        fullpath = os.path.join(root, file) # root is the current directory
        fileName = os.path.splitext(file)[0] # Get filename for new folder name
        arcpy.AddMessage("FileName = {}".format(fileName))

        #Reference MXD
        mxd = arcpy.mapping.MapDocument(fullpath)
        DFList = arcpy.mapping.ListDataFrames(mxd)
        for df in DFList:
            lyrList = arcpy.mapping.ListLayers(mxd, "", df)
            arcpy.AddMessage("Fullpath = {}".format(fullpath))

            for lyr in lyrList:


                lyrName = lyr.name
                if lyr.supports("dataSource"):
                    lyrDatasource = lyr.dataSource
                    lyrDataSetName = lyr.datasetName
                    qname, q_extension = os.path.splitext(lyrDatasource)
                    if q_extension in (".TIF", ".tif",".JPG",".jpg",".png",".PNG",".ECW",".ecw",".sid",".SID",".img",".IMG",".grd",".GRD"):
                        lyrDataSetName = lyrDataSetName[:-4]
                    if lyrDataSetName[:1].isdigit():
                        lyrDataSetName = "y" + lyrDataSetName                        
                    lyrDataSetName1= (lyrDataSetName.replace(" ","").replace("?","").replace(",","").replace(chr(33),"").replace("-","").replace(chr(64),"").replace(chr(36),"").replace(chr(42),"").replace(chr(35),"").replace(chr(59),""))
                    arcpy.AddMessage("lyrName = {}".format(lyrName))
                    arcpy.AddMessage("lyrDatasource = {}".format(lyrDatasource))
                    arcpy.AddMessage("newLayername = {}".format(lyrDataSetName1))
                    destfeature = (str(newFGDB) + "\\" + str(lyrDataSetName1))
                    arcpy.AddMessage("destLayerfull = " +(destfeature))

                    if lyrDatasource not in dataSourceSet:# If datasource not already copied, then copy it
                        arcpy.env.workspace = newFGDB
                        chkpath = (os.path.join(newFGDB, lyrDataSetName1))
                        if arcpy.Exists(destfeature) == True:
                            arcpy.AddMessage("Already exists")
                        elif arcpy.Exists(chkpath) == False:
                            arcpy.AddMessage("New Layer")
                            newLyrPath = arcpy.CopyFeatures_management(lyrDatasource, lyrDataSetName1)
                        else:
                            arcpy.AddMessage("None")

                    lyr.replaceDataSource(newFGDB, "FILEGDB_WORKSPACE", lyrDataSetName1) # Repoint layer datasource to new FGDB
                    arcpy.AddMessage(newFGDB + "    "+ lyrDataSetName1)
                    dataSourceSet.add(lyrDatasource) # Keep track of datasource name to avoid copying same datasource twice
        savefile = str(newPath+"\\"+fileName+".mxd")
        arcpy.AddMessage (savefile)

        mxd.save() # Save new MXD in new folder

Set this up as a script tool and set the parameters as follows:

enter image description here

I copy my mxd's to a single folder and use that as the input folder.. provide an output folder path and a name for the output gdb. It does very simple data comparisons to avoid duplication. It just looks at the layer name... If you had 2 mxd's that both had a layer named "camps" that were meant to point at different datasets it would only copy the first one as it only looks at filenames to decide if it is duplicate data or not.

Once it is done I run another script on the folder to make the mxds all relative path and zip the whole folder.

import arcpy, os

FileName = [] FolderPath = [] FolderPath = arcpy.GetParameterAsText(0)

for FileName in os.listdir(FolderPath): FullPath = os.path.join(FolderPath, FileName) if os.path.isfile(FullPath): BaseName, extension = os.path.splitext(FullPath) if extension.lower() == ".mxd": arcpy.AddMessage(FullPath) mxd = arcpy.mapping.MapDocument(FullPath) mxd.relativePaths = True mxd.save()

Mike
  • 718
  • 4
  • 8