Arc GISに追加されているshapefileをQGISに（またはその逆）

Python（一部手作業）で、ArcMap上に追加されているレイヤをQGISに追加する（またはその逆の）手順を、紹介します。

#Ⅰ.　ArcGISからQGISへ

##Ⅰ-1. ArcGISのPythonコンソールでの作業
ArcMapのPythonコンソールに以下を実行します。

```
#mxdの定義
mxd = arcpy.mapping.MapDocument("CURRENT")
#get layer list
lyr = arcpy.mapping.ListLayers(mxd)


#レイヤの保存先パスをリストに格納
lyrPath =[]
for l in lyr:
	if l.isFeatureLayer ==True or l.isRasterLayer ==True:
		lyrPath.append(l.dataSource)
print(lyrPath)
```
実行結果として、追加されているレイヤの保存先パスがリストで取得される。
通常「arcpy.mapping.ListLayers(mxd)」を実行するとレイヤの一覧を取得できるが、下の図のようにレイヤーがグループになっていると、そのグループもリストに加わってしまい、次の処理でそれぞれのレイヤのパスを取得する段階でエラーになってしまう。
そこで、それぞれのレイヤーのタイプを調べて、ベクターレイヤもしくはラスターレイヤだったらlyrPathという別のリストに入れてあげるということをしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/83691b1e-3744-ebe5-45b8-456e4c95eb8d.png)



（ここでは、基盤地図情報から用意したshpと10mDEMがリスト化されています。）


下の画像の赤枠で囲った、実行結果の保存パスが表示されている部分（「[」から、「]」まで）を範囲選択してコピーしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/631e0f52-61ef-cdd3-5c9c-a7d64ded8821.png)




##Ⅰ-2.  QGISのPythonコンソールでの作業
今度はQGISのpythonコンソールを立ち上げて、以下のコードの「lyrPath = 」に続いて、先ほどArcGISのPythonコンソールでコピーした内容を貼り付けて実行する。

```
lyrPath =  コピーした内容を貼り付け
```


（今回の例の場合だと、こうなる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/4b3d5b8c-8d0e-8cee-decc-0e1fff2f98b3.png)


続いて、以下を実行する。

```
lyrPath.reverse()
for i in lyrPath:
	if i[len(i)-4:] ==".shp":
		iface.addVectorLayer(i,'','ogr')
	else:
	 	iface.addRasterLayer(i,"")
```
完成！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/9da6d5b5-12bf-083b-53ac-dc6ab042dbf5.png)


iface.addVector(Raster)Layerでそれぞれのデータを追加していますが、そのままリスト順で追加すると、次々にレイヤのトップに追加されて、最終的に、ArcGISでのレイヤの並びとQGISのレイヤの並びが逆になってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/d6547e94-24a2-912b-c59b-6a59ac435502.png)


そこでlyrPath.reverse()でリストの並びを逆にしてあげています。
次のforループではパスの最後4文字が「.shp」ならベクターで追加、そうでないならラスターとして追加という感じです。
（.shpじゃないベクターデータならどうするかということはとりあえず無視しています）



#Ⅱ. QGISからArcGISへ

##Ⅱ-1.　QGISのPythonコンソールでの作業
QGISのPythonコンソールに以下を実行。

```
lyrlist = QgsProject.instance().mapLayers()

lyrPath =[]
for i in lyrlist:
	lyrPath.append(lyrlist[i].dataProvider().dataSourceUri())

print(lyrPath)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/0174bf74-f6c2-f52c-235e-00a7b746269d.png)

実行結果として、レイヤーのパスをリストで取得します。
QGISではレイヤ内にグループがあっても、リストには無視してくれます。
しかしこちらで気になるのが、パスを取得すると各レイヤのパスの後ろに「|layerid=0」というのがくっついています。（図中紫枠）
さらにフィルターをかけているレイヤには、後ろに「subset=フィルター式」がはいります（図中青枠）。
これらは、データをロードするときに邪魔になりますが、次の処理で対処するとしてとりあえず気にせず「print(lyrPath)」の実行結果部分（図中赤枠範囲）をコピーします。



##Ⅱ-2.　ArcGISのPythonコンソールでの作業

今度はArcGISのpythonコンソールを立ち上げて、以下のコードの「lyrPath = 」に続いて、先ほどQGISのPythonコンソールでコピーしたレイヤのパスの内容を貼り付けて実行する。

```
lyrPath =  コピーした内容を貼り付け
```


（今回の場合だと、こうなる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/94d2266a-73ac-da3f-8acd-c869931fd5c2.png)


続いて以下を実行。

```
mxd = arcpy.mapping.MapDocument("CURRENT")
df = arcpy.mapping.ListDataFrames(mxd,"")[0]


for i in lyrPath:
	if i.find(".shp") !=-1:
		addlayer = arcpy.mapping.Layer(i[0:i.find(".shp") +4])
		arcpy.mapping.AddLayer(df, addlayer, "BOTTOM")
	else:
		addlayer = arcpy.mapping.Layer(i)
		arcpy.mapping.AddLayer(df, addlayer, "BOTTOM")

```

実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61492/8280dc76-a61f-e0f0-a3df-14928d59a009.png)

無事追加される。

forループでlyrPath内をひとつずつ追加していくのですが、上で書いたとおり、QGISで取得した保存先パスの後ろに「layerid」とか「subset」とか余計な文字が入っています。
そこで、パス内に「.shp」という文字が入っているかを検索し、あればその.shpまでの文字数文までをレイヤーとして読み込む。
ラスターの時にはそういった余計な文字が入っていないので、「.shp」という文字が入っていなければ（＝ラスターの時は）、そのままレイヤとして読み込む。
ということです。
追加の際には"BOTTOM"を指定して、レイヤの最下層に追加するようにしてやれば、QGISでのレイヤの並びと同じになります。



#Ⅲ. 課題
kmlやcsv、xyzタイルなどシェープファイルやラスター以外のデータがレイヤとしてあった場合を対応できてないです。

あと、QGISでレイヤのパスを取得するとフィルター情報も拾えるので、Arcに追加するときにそれも反映できればいいですね。

それはまた追々。