質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • C#

    9051questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Access

    595questions

    Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

Access2013にて.NETのようなDataGrid表示はできますか?

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 987

unto

score 2

 前提・実現したいこと

Access2013にてシステムを作成しております。
当方.NETでの経験は長いほうなのですが、Accessに関しては初心者同様で困っております。

◆質問1
Accessのフォームにおいても、.NetのようなDataGridは扱えるのでしょうか?
Accessのクエリなどを使わず、SQLをコードで記載、実行しDataGridに表示したいと
考えております。
また、Datagirdにてデータを書き換えても「更新ボタン」押下まで
テーブルにには反映させない仕様です。

Viewが利用できると思っておりましたが、それもできないようで、
内部的にデータテーブルでデータを管理するしかないと考えております。

◆質問2
上記Accessでの実装が難しいのであれば、.NETでの開発も視野に入れております。
.NetからAccess2013への接続、データ取得はうまくいきましたが、
Accessのテーブル名称を取得する際に権限のエラーが出てしまいます。
Accessを前バージョンへ保存も試みましたが、うまくいきません。

ご助言をお願い致します。。

追記です。

以下の処理をC#にて実行しました。

            string connectionString = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=C:\\Dev\\sample.accdb; Uid =; Pwd =; ";
            string queryString = "SELECT MSysObjects.Type, MSysObjects.Name, MSysObjects.Flags FROM MSysObjects where MSysObjects.Flags = 0 AND Type = 1 ORDER BY MSysObjects.Type, MSysObjects.Name; ";
            DataTable dt = new DataTable();

            // 読み込み
            try
            {
                using (OdbcConnection connection = new OdbcConnection(connectionString))
                {
                    connection.Open();

                    OdbcDataAdapter adapter = new OdbcDataAdapter(queryString, connection);
                    adapter.Fill(dt);

                    dataGridView1.DataSource = dt;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

adapter.Fill(dt);
を実行した際に、エラーとして以下の内容が表示されます。

エラー内容
ERROR[42000][Microsoft][ODBC Microsoft Access Driver]
'MSysObjects'の読み取り権限がないので、レコードを読み取ることができません。

.NETからAccess2013のテーブル名称情報を取得することは無理なのでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

.NetからAccess2013への接続、データ取得はうまくいきましたが、Accessのテーブル名称を取得する際に権限のエラーが出てしまいます。

DataTable に Access のテーブルからデータを取得できていて、DataGridView には表示できるということですか?

で、「Accessのテーブル名称を取得」とはどういうことでしょう? 質問に提示されているコードにはそのような操作は入ってないように見えますが、その操作が入っているとすると具体的にコードのどれですか?

それから、上記と、

adapter.Fill(dt); を実行した際に、エラーとして以下の内容が表示されます。 

で言っていることが矛盾していませんか。adapter.Fill(dt) でエラーが出るということはデータの取得はうまくいってないということだと思うのですが?

・・・というように、意味が分からないことが多々ありますが、とりあえず一度 Visual Studio のウィザードを使って定番の構成のアプリを作ってみることを提案させてください。

DB が SQL Server の場合ですが、以下のチュートリアル、

チュートリアル : データベースへのデータの保存 (単一テーブル)
https://msdn.microsoft.com/ja-jp/library/0f92s97z(v=vs.120).aspx

・・・のように Visual Studio のデータソース構成ウィザードを利用して型付 DataSet + TableAdapter を作って、それを利用してアプリを作ると、以下のページの図のような構造のアプリが、ほとんど自分でコードを書くこと無しに作れます。

Windows フォーム アプリケーションでのデータへの接続
https://msdn.microsoft.com/ja-jp/library/wxt2cwcc(v=vs.120).aspx

Access でもウィザードが使えますので、同様なことができます。(注)

操作に慣れると 10 分もかからず作れるはずです。今回のような問題に悩むことはなくなり、開発工数は激減するはずです。保守工数も減るはずです。お試しください。

(注)Access でオートナンバーを使っている場合、INSERT した時に DB 側で設定したオートナンバー値を DataSet に書き込むところまでは面倒を見てくれないという点が SQL Server とは違いまが、それを解決する方法はあります。詳しくは以下の記事を見てください。

Access の更新
http://surferonwww.info/BlogEngine/post/2010/09/04/Updating-Access.aspx

【追伸】

今回の問題とは関係ない余計なお世話かもしれませんが、Exception をキャッチするのは止めた方がいいです。理由は以下の記事を見てください。

NETの例外処理 Part.1
https://blogs.msdn.microsoft.com/nakama/2008/12/29/net-part-1/

.NETの例外処理 Part.2
https://blogs.msdn.microsoft.com/nakama/2009/01/02/net-part-2/

.NET 4 からは破損状態例外は catch できなくなっているそうですが、「それでも Catch (Exception e) を使用するのはよくない」ということについては以下の記事を見てください。

破損状態例外を処理する
https://msdn.microsoft.com/ja-jp/magazine/dd419661.aspx

【2018/3/2 13:30 追記】

下の 2018/03/02 12:50 の私のコメントで「OleDbConnection.GetSchema メソッドを利用するのがよさそうです。具体的な方法は別途回答欄に追記しておきます」と書きましたが、それを以下に書きます。

詳しい説明が書いてある Microsoft の文書が見つからず、やってみた結果で判断してますので、ホントにそれで全てのケースで問題なくテーブル名が取得できるのかという不安は若干ありますが・・・

OleDbConnection.GetSchema メソッド (String) の引数(返すスキーマの名前)を "Tables" とすると、テーブルのスキーマ情報(テーブル名を含む)を格納した DataTable が返ってきます。

OleDbConnection.GetSchema メソッド (String)
https://msdn.microsoft.com/ja-jp/library/ms135982(v=vs.110).aspx

DataTable の中には VIEW やシステムテーブルも含まれていますが、テーブルの種類の情報も含まれているのでそれを見てテーブル名のみを取得できます。

DataTable の 3 番目の列にテーブル名が、4 番目の列に種類が格納されているので、種類が "TABLE" ものを取得すれば良いはずです。

以下のコードは、Microsoft のサンプル Northwind2007.accdb からその中のテーブル名を取得する例です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.OleDb;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleAppAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            using (OleDbConnection conn = new OleDbConnection())
            {
                conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=\"C:\\Users\\...\\Northwind2007.accdb\"";
                conn.Open();

                string collectionName = "Tables";
                DataTable table = conn.GetSchema(collectionName);
                foreach (DataRow dataRow in table.Rows)
                {
                    if (dataRow[3].ToString() == "TABLE")
                    {
                        Console.WriteLine(dataRow[2]);
                    }
                }
            }
        }
    }
}

結果は以下の通りで、Northwind2007.accdb に含まれるテーブル名として間違いないことは確認しました。

Budget
Categories
Categories 2003
Customers
Customers 2003
Employee Privileges
Employees
Employees 2003
Inventory Transaction Types
Inventory Transactions
Invoices
Monthly Orders
Order Details
Order Details 2003
Order Details Status
Orders
Orders 2003
Orders Status
Orders Tax Status
Privileges
Products
Products 2003
Purchase Order Details
Purchase Order Status
Purchase Orders
Sales Reports
Shippers
Strings
Suppliers
Suppliers 2003
Switchboard Items

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/02 00:37

    AccessにはMSysObjectsというシステムテーブルがあってそこにテーブル名等の情報があります。
    ですので、queryStringに設定しているSQLがそれにあたることになるかと思います。(SQLが合っているかは検証していませんが)

    キャンセル

  • 2018/03/02 12:50

    > queryStringに設定しているSQLがそれにあたることになるかと思います。

    失礼しました。クエリに目が行ってなかったです。提示されていたコードはテーブルからデータを抽出して DataDridView に表示するものだと思い込んでました。

    .NET の C# アプリからテーブルデータを取得するのは問題なくできていて、現在の課題は接続先の .accdb ファイルにあるテーブル名を取得するということでいいのですね?

    'MSysObjects' に読み取り権限を与えるのは、自分が調べた限りですが、方法が見つからないです。(Zuishin さんが紹介された記事も読みましたが)

    なので、OleDbConnection.GetSchema メソッドを利用するのがよさそうです。具体的な方法は別途回答欄に追記しておきます。

    キャンセル

+1

質問1
Access は .NET でないので同じものはありません。
Accessのフォームでデータを一覧で表示できるようにする方法
フォームの種類(単票・表・データシート・帳票)

質問2
teratail を使っている人たちと比べて開発が長い方なのならどのように聞けばいいかわかるのではありませんか?
長年エラーメッセージを読まずに済ませたのですか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/01 01:01

    ご返信いただき大変有難う御座いました。
    また、質問内容に関し、不足事項があり大変申し訳ございません。
    プロの方々からご回答をいただけると期待してしまい、内容を割愛してしまいました。。
    今後気を付けて参ります。

    質問2に関しての追記致しました。
    何卒、ご助言いただきたく宜しくお願い致します。。

    キャンセル

  • 2018/03/01 01:02

    プロはエラーメッセージを読まないのですか?

    キャンセル

  • 2018/03/01 01:08

    いえいえ。そういった意味ではございません。
    お気を悪くしてしまったら申し訳ございません。

    長年経験している方は「あーこの問題ねー」と推測できるものなのかと思っておりました。
    大変失礼いたしました。

    キャンセル

  • 2018/03/01 01:10

    http://q.hatena.ne.jp/mobile/1177202738

    とりあえずこれを試してみてください。
    何の情報もなく答えられるのはプロではなくエスパーだと思います。

    キャンセル

  • 2018/03/01 01:12 編集

    何の手がかりも無いのにあーこの問題ねーとすぐ見当がつくほどよくある問題ならエラーメッセージでググればすぐ解決方法が見つかりますので次回からはエラーを無視しないでください。

    キャンセル

  • 2018/03/01 01:36

    Zuishinさん
    いろいろとご助言いただきありがとうございました。
    今後気を付けていきます。

    キャンセル

0

質問1について、Accessの実装を考えた場合以下のようになるかと思います。

・accessにワークテーブルを持ち、そのテーブルをレコードソースとして指定する。
・表示や更新の場合、そのワークテーブルを介在として実テーブルへはSQLでアクセスする。

上記とすることで、排他の管理も実テーブルにアクセスする瞬間に限定でき、また、mdbのテーブルを利用することで、Accessの機能も利用できることになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/01 11:01

    saziさん
    コメント頂き有難うございます。

    また不明点などありましたら質問してしまうかもしれませんが、
    頂いた設計アイデアでチャレンジしてみます。

    ありがとうございました。

    キャンセル

  • 2018/03/01 16:16

    ワークテーブルを使用する際にはデータの追加削除の繰り返しになりますので、DBが肥大化して破損しないように、常に最適化されるようにして下さい。
    ※ワークテーブルと言わず、アクセスのテーブルを使用する場合には最適化は必須と考えた方が良いですけど。

    キャンセル

同じタグがついた質問を見る

  • C#

    9051questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Access

    595questions

    Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。