C++ Builder XE4 > Excel 2016 + OLE > csvファイルを読込んで、コピーし、xlsxファイルにペーストして、別名保存

```txt:動作環境
- 実装
    - C++ Builder XE4
- 確認
    - Windows 8.1 Pro
    - Excel 2016
```

### 処理概要

1. xlsxファイルを開く
2. csvファイルを開き、Range指定してコピーする
    - `B1:B500`の範囲
3. 1で開いたファイルにペースト
4. 1で開いたファイルを別名保存

### code

- srcFile: 読込みcsvファイル名
- baseFile: 読込みxlsxファイル名
- dstFile: 保存ファイル名

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <System.Win.ComObj.hpp>  // EXCEL処理用

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------


__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
	String curDir = ExtractFileDir(Application->ExeName);

	WideString srcFile = curDir + "\\0624\\240000_1.csv";
	WideString baseFile = curDir + "\\base.xlsx";
	WideString dstFile = curDir + "\\out.xlsx";

	Variant ExcelApp = CreateOleObject("Excel.Application");

	DWORD stTim = GetTickCount();

	try
    {
		Variant xls_books;
		Variant xls_abook;
		Variant book_csv; // データ読込み用csv
		Variant sheet_csv; // データ読込み用csv
		Variant xls_sheets;
		Variant xls_asheet;

		try {
			Memo1->Lines->Add(L"start: " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));

			// Excel初期処理
			ExcelApp.OlePropertySet("Visible", false); // Excel not shown
			ExcelApp.OlePropertySet("DisplayAlerts", false); // No dialog for overwrite
			ExcelApp.OlePropertySet("ScreenUpdating", false); // 処理の高速化のため
			xls_books = ExcelApp.OlePropertyGet("Workbooks");

			// 1. 保存対象ファイル
			xls_abook = xls_books.OleFunction("Open", baseFile);
			xls_abook.OlePropertyGet("Sheets", 1).OleProcedure("Select");
			xls_asheet = xls_abook.OlePropertyGet("ActiveSheet");

			Memo1->Lines->Add(L"fin:Open " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));

			// 2. 行列のコピー
			book_csv = xls_books.OleFunction("Open", srcFile);
			book_csv.OlePropertyGet("Sheets", 1).OleProcedure("Select");
			sheet_csv = book_csv.OlePropertyGet("ActiveSheet");
			Variant wrkRange = sheet_csv.OlePropertyGet("Range", WideString("B1:B500"));
			wrkRange.OleProcedure("Copy");
			book_csv.OleProcedure("Close");

			Memo1->Lines->Add(L"fin:Copy " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));

			// 3. ペースト
			xls_asheet.OlePropertyGet("Cells", /*row=*/1, /*column=*/3).OleProcedure("Select");
			xls_asheet.OleProcedure("PasteSpecial"); // 書式なしペースト

			Memo1->Lines->Add(L"fin:Paste " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));

			// 4. 別名保存
			ExcelApp.OlePropertySet("ScreenUpdating", true); // 高速化のための設定を戻す
			xls_abook.OleProcedure("SaveAs", dstFile); //開いた*.xlsxを別名保存
			ExcelApp.Exec(Procedure("Quit"));

			Memo1->Lines->Add(L"fin:Save " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz"));


			DWORD edTim = GetTickCount();
			String msg = IntToStr((int)(edTim - stTim)) + L"(msec) has passed";

			msg = msg + L"\r\n" + L"Save to [" + dstFile + L"]";
			ShowMessage(msg);
		}
		__finally
		{
			xls_asheet = Unassigned(); // 変数を初期状態に
			xls_sheets = Unassigned();
			xls_abook = Unassigned();
			xls_books = Unassigned();
			book_csv = Unassigned();
			sheet_csv = Unassigned();
		}
	}
	__finally
	{
		ExcelApp = Unassigned();
	}
}
//---------------------------------------------------------------------------
``` 

### 備考

csvファイルから読込む部分を別関数化しようとしたが、Variant型の扱いが問題なのか、エラーが出た。

### 備考2
(追記 2018/07/11)

```cpp
xls_asheet.OleProcedure("PasteSpecial"); // 書式なしペースト
```

上記の実行では「書式なし」にはなっていないだろう。
[形式を選択して貼り付ける(PasteSpecialメソッド)](http://www.moug.net/tech/exvba/0050104.html)を参考に下記のようにしてみたが、「WorksheetクラスのPasteSpecialメソッドが失敗しました。」というエラーになる。

```cpp
xls_asheet.OleProcedure("PasteSpecial", -4163); // 書式なしペースト
```