マリオネット・スクリプト解説講座

第44回「Excelデータの読み込み」

FundamentalsArchitectLandmarkSpotlightDesigner2023

今回は、Excelフォーマットで入力されたデータをVectorworksのスクリプトを使って直接参照する方法をご紹介します。(執筆:A&A 川崎)

Excelデータ、みなさまも利用される機会多いかと存じます。Vectorworks 2021以降のプログラミング環境ではExcelフォーマットのデータを直接入出力できる関数が用意されています。

今回はVectorScript/PythonからExcelデータにアクセスしてみましょう。

準備として、デスクトップなど任意の場所にExcelのファイルを配置してください。敷地図の座標データのシートなど、普段お使いのもので構いません。ここでは、頂点座標(x,y,z)がシートごとに入力されているデータsample.xlsxをデスクトップに配置して使用しています。

44-1. Excelのファイルを開く

早速ですが、EXL_ReadFileを使用してExcelのファイルを開きます。

VectorScript:

FUNCTION EXL_ReadFile( FilePath : STRING ) : BOOLEAN;

Python:

def vs.EXL_ReadFile( FilePath ) : return BOOLEAN

EXL_ReadFileはファイルをオープンしてこれからアクセスしますよという準備の関数です。関数名に “Read” が含まれているので読み込みをイメージしてしまいますが、データの読み込みは次のステップで行います。

また、ファイルをオープンした場合には、対として最後にファイルを閉じてアクセスを終了することを伝える必要があります。

EXL_ReadFileの対になる関数はEXL_CloseBookです。

VectorScript:

FUNCTION EXL_CloseBook : BOOLEAN;

Python:

def vs.EXL_CloseBook() : return BOOLEAN

Excelデータの入出力では、EXL_ReadFileEXL_CloseBookの間にデータの読み書きの処理を追加していくことになります。

VectorScript:

PROCEDURE sample;
VAR
	boo : BOOLEAN;
BEGIN
	boo := EXL_ReadFile( 'ファイルパス' );
	{ココの間で読み込む処理を入れます}
	boo := EXL_CloseBook;
END;
Run( sample );

Python:

import vs

boo = vs.EXL_ReadFile( 'ファイルパス' )
#	ココの間で読み込む処理を入れます
boo = vs.EXL_CloseBook()

44-2. ファイルパスの指定

EXL_ReadFileの解説に戻ります。EXL_ReadFileの引数にはExcelファイルのパスを指定します。デスクトップに配置したsample.xlsxのパスを指定する場合は次のようになります。

VectorScript:

PROCEDURE sample;
VAR
	boo : BOOLEAN;
BEGIN
	boo := EXL_ReadFile( 'Ventura HD¥Users¥aa¥Desktop¥sample.xlsx' );
        boo := EXL_CloseBook;
END;
Run( sample );

Python:

import vs

boo = vs.EXL_ReadFile( 'C:¥Users¥aa¥Desktop¥sample.xlsx' )
boo = vs.EXL_CloseBook()

ここで一つ応用です。

ファイルのパスを可変にして、スクリプトの実行時にファイル選択ダイアログから任意のファイルを指定できるように変更してみましょう。

ファイル選択ダイアログを使用したパスの指定ではGetFileNを使用します。

VectorScript:

FUNCTION GetFileN( title, defaultFolder, mask, fileName ) : BOOLEAN;

Python:

def  vs.GetFileN(title, defaultFolder, mask):return (BOOLEAN, fileName)

GetFileNの3番目の引数に「xlsx」を渡すことで、ファイル選択ダイアログ上ではExcelファイルしか選択できないようになります。

ファイル選択ダイアログでキャンセルした場合にはFalseを返しますので、その後の処理を行わないようにif文で分岐しておきましょう。

VectorScript:

PROCEDURE sample;
VAR
	fileName : DYNARRAY[] of CHAR;
	boo : BOOLEAN;
BEGIN
	boo := GetFileN( 'ファイルを選んでください', '', 'xlsx', fileName );
	IF boo THEN
	BEGIN
		boo := EXL_ReadFile( fileName );
		{ココの間で読み込む処理を入れます}
		boo := EXL_CloseBook;
	END;
END;
Run( sample );

Python:

import vs

boo, fileName = vs.GetFileN( 'ファイルを選んでください', '', 'xlsx' )
if boo:
	boo = vs.EXL_ReadFile( fileName )
	#	ココの間で読み込む処理を入れます
	boo = vs.EXL_CloseBook()

44-3. データ読み込み位置の確認

データの読み込みを実行するとき、ファイルのどの位置のデータを読み込むのかの情報が必要になります。具体的には、シートのIDや行番号、列番号などの情報です。

データの読み込み位置が固定で決まっていれば事前に確認して指定することも可能ですが、データの数が決まっていない場合など可変長のデータを読み込みたい場合に、スクリプトの実行中にファイルのフォーマットの情報を取得しながら読み込み位置を調整することも可能です。

シートの数の取得:EXL_GetSheetCnt

VectorScript:

FUNCTION EXL_GetSheetCnt( VAR outSheetCount:INTEGER ) : BOOLEAN;

Python:

def vs.EXL_GetSheetCnt() : return ( BOOLEAN, outSheetCount )

VectorScript:

VectorScript:
PROCEDURE sample;
VAR
	fileName : DYNARRAY[] of CHAR;
	outSheetCount : INTEGER;
	boo : BOOLEAN;
BEGIN
	boo := GetFileN( 'ファイルを選んでください', '', 'xlsx', fileName );
	IF boo THEN
	BEGIN
		boo := EXL_ReadFile( fileName );
		boo := EXL_GetSheetCnt( outSheetCount );AlrtDialog( Num2StrF( outSheetCount ) );
		boo := EXL_CloseBook;
	END;
END;
Run( sample );

Python:

import vs

boo, fileName = vs.GetFileN( 'ファイルを選んでください', '', 'xlsx' )
if boo:
	boo = vs.EXL_ReadFile( fileName )
	boo, outSheetCount = vs.EXL_GetSheetCnt();vs.AlrtDialog( vs.Num2StrF( outSheetCount ) );
	boo = vs.EXL_CloseBook()

シートの名前を取得:EXL_GetSheetName

VectorScript:

FUNCTION EXL_GetSheetName( sheetIndex : INTEGER; VAR outSheetName : STRING ) : BOOLEAN;

Python:

def vs.EXL_GetSheetName( sheetIndex ) : return ( BOOLEAN, outSheetName )

シートのIDを取得:EXL_GetSheetIndex

※シートのIDは0から始まります。

VectorScript:

FUNCTION EXL_GetSheetIndex( sheetName : STRING; VAR outSheetIndex : INTEGER ) : BOOLEAN;

Python:

def vs.EXL_GetSheetIndex( sheetName ) : return ( BOOLEAN, outSheetIndex )

VectorScript:

PROCEDURE sample;
VAR
	fileName : DYNARRAY[] of CHAR;
	outSheetCount : INTEGER;
	outSheetName : STRING;
	outSheetIndex : INTEGER;
	ii : INTEGER;
	boo : BOOLEAN;
BEGIN
	boo := GetFileN( 'ファイルを選んでください', '', 'xlsx', fileName );
	IF boo THEN
	BEGIN
		boo := EXL_ReadFile( fileName );
		boo := EXL_GetSheetCnt( outSheetCount );
		FOR ii := 1 TO outSheetCount DO
		BEGIN
			boo := EXL_GetSheetName( ii-1, outSheetName );AlrtDialog( outSheetName );
			boo := EXL_GetSheetIndex( outSheetName, outSheetIndex );AlrtDialog( Num2StrF( outSheetIndex ) );
		END;
		boo := EXL_CloseBook;
	END;
END;
Run( sample );

Python:

import vs

boo, fileName = vs.GetFileN( 'ファイルを選んでください', '', 'xlsx' )
if boo:
	boo = vs.EXL_ReadFile( fileName )
	boo, outSheetCount = vs.EXL_GetSheetCnt()
	for ii in range( outSheetCount ):
		boo, outSheetName = vs.EXL_GetSheetName( ii );vs.AlrtDialog( outSheetName )
		boo, outSheetIndex = vs.EXL_GetSheetIndex( outSheetName );vs.AlrtDialog( vs.Num2StrF( outSheetIndex ) );
	boo = vs.EXL_CloseBook()

シートごとの行数と列数の取得:EXL_GetSheetSize

VectorScript:

FUNCTION EXL_GetSheetSize( sheetIndex : INTEGER; VAR outRows : INTEGER; VAR outColumns : INTEGER ) : BOOLEAN;

Python:

def vs.EXL_GetSheetSize( sheetIndex ):return ( BOOLEAN, outRows, outColumns )

VectorScript:

PROCEDURE sample;
VAR
	fileName : DYNARRAY[] of CHAR;
	outSheetCount : INTEGER;
	outSheetName : STRING;
	outSheetIndex : INTEGER;
	outRows, outColumns : INTEGER;
	ii : INTEGER;
	boo : BOOLEAN;
BEGIN
	boo := GetFileN( 'ファイルを選んでください', '', 'xlsx', fileName );
	IF boo THEN
	BEGIN
		boo := EXL_ReadFile( fileName );
		boo := EXL_GetSheetCnt( outSheetCount );
		FOR ii := 1 TO outSheetCount DO
		BEGIN
			boo := EXL_GetSheetSize( ii-1, outRows, outColumns );
                        AlrtDialog( Concat( Num2StrF( outRows ), ',', Num2StrF( outColumns ) ) );
		END;
		boo := EXL_CloseBook;
	END;
END;
Run( sample );

Python:

import vs

boo, fileName = vs.GetFileN( 'ファイルを選んでください', '', 'xlsx' )
if boo:
	boo = vs.EXL_ReadFile( fileName )
	boo, outSheetCount = vs.EXL_GetSheetCnt()
	for ii in range( outSheetCount ):
		boo, outRows, outColumns = vs.EXL_GetSheetSize( ii );
		vs.AlrtDialog( vs.Concat( vs.Num2StrF( outRows ), ',', vs.Num2StrF( outColumns ) ) );

	boo = vs.EXL_CloseBook()

44-4. データを読み込む

ここまでで、Excelのファイルを開き、シート数も、行、列も確認できるようになったので、最後は実際にデータを取得してVectorworksでの作図に使用します。

ここでは、3つのシートにそれぞれ三角形、四角形、五角形の頂点座標(x,y,z)が入力されているデータを使用します。

VectorScript:

FUNCTION EXL_GetCellValue( sheetIndex : INTEGER; cellRow : INTEGER; cellColumn : INTEGER; VAR outFormula : STRING; VAR outString : STRING; VAR outLeaderStr : STRING; VAR outTrailerStr : STRING; VAR outValue : REAL ) : BOOLEAN;

Python:

def vs.EXL_GetCellValue( sheetIndex, cellRow, cellColumn ):return ( BOOLEAN, outFormula, outString, outLeaderStr, outTrailerStr, outValue )

データを取り込もうとした場合、基本的にはフォーマットはわかっているため、それに併せてデータを読み込んで使用します。

今回の想定はnシートのデータが用意されていて、1行に3列のX,Y,Z座標値がn列あるとします。このデータから、次のような仕様でコーデイングします。

    • シートごとにレイヤを作成する
    • 座標値は3D多角形の頂点として取り込む

Excelデータから1行ごとにx,y,zの値を取得して、Add3DPt(x,y,z)とすることで頂点として定義していきます。

BeginPoly3DEndPoly3Dの間でAdd3DPtを実行した数だけ、3D多角形に頂点が追加されます。

※Excelのシート、行、列ともにEXL_GetCellValueで使用するIDは1はでなく0からのスタートになります。

VectorScript:

PROCEDURE sample;
VAR
	fileName : DYNARRAY[] of CHAR;
	outSheetCount : INTEGER;
	outSheetName : STRING;
	outSheetIndex : INTEGER;
	outRows, outColumns : INTEGER;
	outFormula, outString, outLeaderStr, outTrailerStr : STRING;
	outValue : REAL;
	grid : ARRAY[1..3] of REAL;
	hh : HANDLE;
	ii, jj, kk : INTEGER;
	boo : BOOLEAN;
BEGIN
	boo := GetFileN( 'ファイルを選んでください', '', 'xlsx', fileName );
	IF boo THEN
	BEGIN
		boo := EXL_ReadFile( fileName );
		boo := EXL_GetSheetCnt( outSheetCount );
		FOR ii := 1 TO outSheetCount DO
		BEGIN
			boo := EXL_GetSheetName( ii-1, outSheetName );
			hh := CreateLayer( outSheetName, 1 );
			boo := EXL_GetSheetSize( ii-1, outRows, outColumns );
			ClosePoly;
			BeginPoly3D;
			FOR jj := 1 TO outRows DO
			BEGIN
				FOR kk := 1 TO outColumns DO
				BEGIN
					boo := EXL_GetCellValue( ii-1, jj-1, kk-1, outFormula, outString, outLeaderStr, outTrailerStr, grid[kk] );
				END;
				Add3DPt( grid[1], grid[2], grid[3] );
			END;
			EndPoly3D;
		END;
		boo := EXL_CloseBook;
	END;
END;
Run( sample );

Python:

import vs

boo, fileName = vs.GetFileN( 'ファイルを選んでください', '', 'xlsx' )
if boo:
	boo = vs.EXL_ReadFile( fileName )
	boo, outSheetCount = vs.EXL_GetSheetCnt()
	for ii in range( outSheetCount ):
		boo, outSheetName = vs.EXL_GetSheetName( ii )
		hh = vs.CreateLayer( outSheetName, 1 )
		boo, outRows, outColumns = vs.EXL_GetSheetSize( ii )
		vs.ClosePoly()
		vs.BeginPoly3D()
		for jj in range( outRows ):
			grid = []
			for kk in range( outColumns ):
				boo, outFormula, outString, outLeaderStr, outTrailerStr, outValue = vs.EXL_GetCellValue( ii, jj, kk )
				grid.append( outValue )
			vs.Add3DPt( tuple( grid ) )
		vs.EndPoly3D()
	boo = vs.EXL_CloseBook()

スクリプトを実行すると、Excelに入力された座標データをもとに3D多角形が作図されます。

この機能を利用できる製品

Fundamentals

Vectorworks Fundamentals

2D/3D汎用作図機能に、プレゼンボード作成機能や図面と連動できる表計算機能など、数多くの基本作図機能に加え、高品質レンダリング&3Dビジュアライズ機能を搭載したVectorworksシリーズの基本製品
詳細情報 購入ページ

Architect

Vectorworks Architect

建築設計や内装、ディスプレイデザインに対応した先進的なBIM・インテリア設計支援機能、拡張機能、さらには豊富な建築向けのデータライブラリを搭載した建築/内装業界向け製品
詳細情報 購入ページ

Landmark

Vectorworks Landmark

地形モデルや多彩な植栽、灌水設備計画等に対応するランドスケープデザイン機能、さらには豊富な造園向けのデータライブラリを搭載した都市計画/造園業界向け製品
詳細情報 購入ページ

Spotlight

Vectorworks Spotlight

ステージプランニングやライティング計画に対応した先進的な舞台照明計画支援機能、さらには各種メーカー製のトラスや照明機材、音響機器等の豊富なデータライブラリを搭載したエンタテインメント業界向け製品
詳細情報 購入ページ

Designer

Vectorworks Design Suite

専門分野別(建築設計/ディスプレイデザイン、ランドスケープデザイン、ステージデザイン&スポットライトプランニング)の設計支援機能、拡張機能、さらには豊富なデータライブラリを搭載した最上位の製品
詳細情報 購入ページ