Toshichan4
@Toshichan4

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

C# で Excel の名前が定義されたセルの名前を取得する

C# で EXCELの名前が定義されたセルを列挙して
その中から、目的の名前を持ったセルに対して
読み書きしたいと考えています。

その前段階として、名前が定義されていることが
分かっているセルの定義された名前を取得してみようと
考えましたが、その方法が分かりません。
どなたかご教示願います。

(添付のソースファイルの一番下のほうで
 取得を試みています)

すでに開かれている EXCEL シートにアクセスする必要があり
NetOfficeFw.Excel を使用しています。
今回の問題のほかに、NetOfficeFw.Excel の使い方に関する
情報があれば合わせてご教示願います。
(この問題も含め、NetOfficeFw.Excel の使い方に関する
 情報を得ようと、NetOfficeFw.Excel のサイト
   https://netoffice.io/
も見てみたのですがほぼ理解不能で‥‥)

当方、Windows プログラミング、C# ともにほぼほぼ
初心者です。

該当するソースコード

C#
VSCode の winforms project
ちなみに csproj は下の通り

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net7.0-windows</TargetFramework>
    <Nullable>enable</Nullable>
    <UseWindowsForms>true</UseWindowsForms>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="NetOfficeFw.Excel" Version="1.9.4"/>
  </ItemGroup>
</Project>

ソースコードは下記です。

///////////////////////////////////////////////////////
//	すでに開かれているEXCELのBookに対して操作を行う
//	sheet名でシートを選択し、名前が定義されている
//	ことが分かっているセルの 定義された名前を取得する
///////////////////////////////////////////////////////


using System.Security.Cryptography.X509Certificates;
using NetOffice.ExcelApi;
using NetOffice.Extensions.Conversion;
using NetOffice.Extensions.Invoker;
using Excel = NetOffice.ExcelApi;
//using Microsoft.Office.Interop.Excel;

namespace ExcelOperationProc

{
    public partial class Form1 : Form
    {
        Excel.Application xlApp;
        Excel.Workbook xlBook;
        Excel.Worksheet xlSheet;
        Excel.Range xlRange;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
			string debugMessage;


			string _testExcelPath = @"C:\**********\********.xlsx";
			string path = Path.GetFileName(_testExcelPath);
			xlApp = Excel.Application.GetActiveInstance();

			if (xlApp == null) {
				debugMessage = "Excel Book は開かれていません";
				MessageBox.Show(debugMessage,
				"到達  DebugMsg",
				MessageBoxButtons.OK);

				return;
			}

			xlApp.Visible = true;

			var i = 1;	//	WorksheetsやWorkbooks等、Excelのコレクションは常に1オリジン
			var findFlag = 0;
			foreach (Excel.Workbook workbook in xlApp.Workbooks) {
				if (string.Compare(workbook.Name, path, true) == 0) {	// 一致
					findFlag = 1;
					break;
				}
				i++;
			}
			if (findFlag == 0) {
				debugMessage = "目的の Excel Book は開かれていません";
				MessageBox.Show(debugMessage,
				"到達  DebugMsg",
				MessageBoxButtons.OK);

				return;
			}

			xlBook = xlApp.Workbooks[i];
			xlSheet = (Excel.Worksheet)xlBook.Worksheets[1];

			// ここで開いた EXCEL シートの E10セル, cell(10,5) には
			// "NamedCell_E10" の名前を定義している

			// 名前つきセルへ 名前をもとにアクセス  <== これは成功
			xlRange = xlSheet.Range("NamedCell_E10");
			var NamedCellValue = xlRange.Value;

				if (NamedCellValue != null) {
					debugMessage = "value of cell(10,5) = " + NamedCellValue;
					MessageBox.Show(debugMessage,
					"到達  DebugMsg",
					MessageBoxButtons.OK);
				}

			// 名前つきセルの名前を取得  <== これがうまくできない
			// ちなみに 下のコードでは
			//		name of cell(10,5) = Name
			// と表示される。

				if (xlRange.Name != null) {
					debugMessage = "name of cell(10,5) = " + xlRange.Name;
					//debugMessage = "name of cell(10,5) = " + xlRange.Name.ToString();	// 結果は上と同じ
					MessageBox.Show(debugMessage,
					"到達  DebugMsg",
					MessageBoxButtons.OK);
				}

		}

	}
}

自分で試したこと

当初、Microsoft.Office.Interop.Excel で
進めたものの、すでに開かれた Excel にアクセス
するところでつまずき、NetOfficeFw.Excelに転進
NetOfficeFw.Excelで、すでに開かれた Excel にアクセス
することには成功したのですが、今回の問題に遭遇しました。

0

1Answer

// 名前つきセルの名前を取得 <== これがうまくできない

確認ですが、
取得したい、名前つきセルの「名前」とは、今回の場合だと「NamedCell_E10」でしょうか? セル番地の「E10」でしょうか?

0Like

Comments

  1. @Toshichan4

    Questioner

    セル番地 E10 に “NamedCell_E10”という名前を付けています。

    なお、最初の質問のソースコードで、

    		// 名前つきセルへ 名前をもとにアクセス  <== これは成功
    		xlRange = xlSheet.Range("NamedCell_E10");
    		var NamedCellValue = xlRange.Value;
    
    			if (NamedCellValue != null) {
    				debugMessage = "name of cell(10,5) = " + NamedCellValue;
    				MessageBox.Show(debugMessage,
    				"到達  DebugMsg",
    				MessageBoxButtons.OK);
    			}
    

    の部分の
    debugMessage = "name of cell(10,5) = " + NamedCellValue;
    は、本来
    debugMessage = "value of cell(10,5) = " + NamedCellValue;
    としないと誤解を生みやすいので、修正しました。

  2. セル番地 E10 に “NamedCell_E10”という名前を付けています。

    それは理解しています。
    今回のコード上で取得したい「名前」の具体値を確認しています。
    “NamedCell_E10”でしょうか?

  3. @Toshichan4

    Questioner

    はい、その通りです。

    image.png

    image.png

  4. 上のコードにある、xlRange.Nameは、期待されている「名前」を示すものではありません。おそらく"=Sheet1!$E$10"となっているかと思います。


    Excelの「名前」とは、(例えば、A1:E10のような)セル範囲に付ける名前です(セル範囲として、ある一つのセルだけの場合もあります)。

    よって、(例えば、A1とかE10とか)特定のセルに対する「名前」を見つけたい場合は、「名前」からセル範囲を求めて、そのセル範囲に、期待するセルが含まれているか、と、すべての「名前」についてチェックする必要があります。
    ある特定のセルが、複数の「名前」に含まれる場合もあり得ます。
    (「1セル=1名前」と、限定すれば、見つける処理を簡略化はできますが)


    元々の目的は、

    名前が定義されたセルを列挙して
    その中から、目的の名前を持ったセルに対して
    読み書きしたい

    ということでしたら、定義されたすべての「名前」を列挙して、それぞれの「名前」に定義されたセル範囲をチェックすればよいと思います。

    定義されたすべての「名前」は、ActiveWorkbook.Namesで取得できます。上のコードだとxlBook.Namesですかね。Nameのコレクション(配列)となっているので、ループforeachでチェックすればよいと思います。

    foreach (Excel.Name name in xlBook.Names) {
        // name.Name 「名前」の名前 ex, "NamedCell_E10"
        // name.RefersTo 「名前」が示すセル範囲   フォーマット:"シート名!セル範囲" ex, "Sheet1!$E$10"
        // name.RefersToR1 「名前」が示すセル範囲   フォーマット:"シート名!セル範囲(R1C1形式)" ex, "Sheet1!R10C5"
        if ( ・・・
    }
    
  5. @Toshichan4

    Questioner

    ありがとうございます。
    ご教示いただいた方法で無事名前の取得、および
    その名前が示すセル範囲の取得ができました。

    セルの名前はセルに所属する情報だと思っていましたが、
    workbook または worksheet に所属する情報なのですね。
    承知しました。
    ( セル範囲の名前の特殊な場合がセルの名前である
      ことを考えればセルの上位概念の worksheet 以上に
      所属するのは当然ですね。)

    ところで

    上のコードにある、xlRange.Nameは、期待されている「名前」を示すものではありません。おそらく"=Sheet1!$E$10"となっているかと思います。

    に関しては、メッセージボックスで
    debugMessage = "name of cell(10,5) = " + xlRange.Name;
    によって出力させた表示は
     name of cell(10,5) = Name
    でした。

  6. xlRange.Nameは、"Name"だったということですね。謎です・・・。

Your answer might help someone💌