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

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

新規登録して質問してみよう
ただいま回答率
85.37%
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

Q&A

解決済

4回答

635閲覧

HTMLコードをデータベースに保管し、CSVで入出力して管理を行いたい

smaeda

総合スコア18

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

VB.NET

Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

0グッド

0クリップ

投稿2024/08/09 09:02

実現したいこと

・データベースの商品マスタテーブル内に「HTMLコード」を保存したい
・更に、その商品マスタをシステムでCSVとして出力 → 「HTMLコード」を一括で更新 → もう一度取込を行う事でマスタテーブルに値を反映させたい
・CSVはテキストエディタではなく、Excelで管理を行いたい

※HTMLコードをテーブル内に保存する事自体が推奨されていませんが、社内システムなのでご勘弁を・・・
※データの行数が多いためCSV上で一括更新を行いたいという背景があります。

発生している問題・分からないこと

保存する文字列が「HTMLコード」のため、改行とダブルクォーテーションが含まれており、CSVがうまく開けません。
もちろん列ごとにダブルクォテーションで囲み、HTMLコード内のダブルクォーテーションはエスケープすれば解決するかと思いますが、運用の都合上、エスケープせずにCSVに入力したいとの事でした。

そのため敢えてダブルクォーテーションで囲まずにCSVを出力してみましたが、Excelで開くと改行部分で列がずれてしまったり、自動的にダブルクォーてションで囲まれてしまったりと、不安定な動きになりました。

そもそもの仕様が非推奨の要件だらけなため、正攻法では実装できないとは思っており、もし何か回避アイディアのようなものがございましたら、お知恵をお貸しいただけますと幸いです。

該当のソースコード

特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

・ぐぐった所、ダブルクォートのエスケープを解決例として挙げており、今回の要件を満たせませんでした。
・敢えて項目をダブルクォートで囲まず出力したが、改行部分で列がずれたり、勝手にダブルクォートがついたりと、不安定な動きをした。

補足

特になし

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pea

2024/08/09 09:36

どこまで正常に出来ているかを明確にした方が良いと思います csvファイルをテキストエディタで開いて問題ないのであれば、Excelの自動変換機能が問題になっていると思います。 そうなると質問内容はExcelでHTMLコードを自動変換しないように開くにはどうすればいいですか? となります。
tezcello

2024/08/09 09:49

> 社内システムなのでご勘弁を・・・ > 運用の都合上、エスケープせずにCSVに入力したい 知っていて目を背けると、無駄な費用を掛けて遠回りする事にしか成らないのでは? __現に手詰まってるでしょ? 特に後者はCSVの根幹を否定しているのと同じなので、CSVを経由する事で破綻します。 根本的に変更(例えばマークダウン的な記述とかCSVを利用しない)しないと解決はムリだと思います。 保存された値を目で見るという事をしないのを徹底(必ずシステムの機能を通して確認)すれば、CSVにどんな状態で記録されているかは関係なくなると思うのですが。 > 回避アイディアのようなものがございましたら Excel -> CSV -> Web(PHP)アプリ の形態は諦めた方が良いかと。 システムをExcel(あるいはAccess併用)上だけで(VBA等で)完結するのが良いのでは?
otn

2024/08/10 05:02 編集

> もちろん列ごとにダブルクォテーションで囲み、HTMLコード内のダブルクォーテーションはエスケープすれば解決するかと思いますが、運用の都合上、エスケープせずにCSVに入力したいとの事でした。 データ中の"を""にしない場合、そうしたものはCSV形式ではないので、 > 更に、その商品マスタをシステムでCSVとして出力 と矛盾します。 案1:CSV形式をつらぬいて、CSV形式で出力する(やり方はご承知の通りです) 案2:CSV形式を諦めて、数歩戻って「じゃあ、どんなファイル形式でどういう手順でやりとりする?」から再検討
logres_Fan

2024/08/09 13:08

> そもそもの仕様が非推奨の要件だらけなため  怪しい仕事と判明した時点で撤退しないのかしら?
Lhankor_Mhy

2024/08/10 00:44 編集

yambejp さんのご回答の通り、CSVのダブルクォートをエスケープすればいいのではないかと思いました。 クライアントの希望は ・CSVはテキストエディタではなく、Excelで管理を行いたい ・運用の都合上、エスケープせずにCSVに入力したい なのですから、要求されているものは「Excel上ではエスケープせずに入力したい」だと思います。 その場合、CSVの出力段階でエスケープしても問題ないはずです。 その担当営業に詳細を確認してみてはいかがでしょうか。
guest

回答4

0

HTML はダブルクォーテーションがなくても書けることは書けます。属性はシングルクォートで書けますし、場合によってはクォートなしでも書けます、しんどいですが。
https://html.spec.whatwg.org/multipage/syntax.html#unquoted

なので、属性値にはシングルクォート、テキストには文字参照を使ってくれるようにクライアントにお願いしてみるとか……? いわゆる「運用でカバー」ってやつです。
運用側でうっかりダブルクォートを使った場合は、受け入れたCSVにエスケープされたダブルクォートが存在すると思うので、そこで受け入れエラーを返せばなんとかなる……? 20年ぐらい前の古き良き情報システムって感じですが……

投稿2024/08/10 08:22

編集2024/08/10 08:26
Lhankor_Mhy

総合スコア36898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

smaeda

2024/08/15 08:43

ベストアンサーは別の方を選ばせていただきましたが、 確かにHTMLはダブルクォーテーションが無くとも書けるという発想が目から鱗でした。 ご回答いただきありがとうございました。
guest

0

たとえばCSVをこういうデータにするとよいです

CSV

11,"hoge","<html> 2<body> 3<div class=""test"">test</div> 4</body> 5</html>" 62,"fuga","<html> 7<body> 8<div class=""test"">test</div> 9</body> 10</html>"
  • 数値はそのまま、文字列はダブルクォーテーションでエンクローズする
  • セパレーターにはカンマを指定
  • 文字列の途中にダブルクォーテーションが入るような場合は二重のダブルクォーテーションにエスケープする

投稿2024/08/09 09:49

yambejp

総合スコア116468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

smaeda

2024/08/15 08:43

ベストアンサーは別の方を選ばせていただきましたが、大変参考になりました。 ご回答いただきありがとうございました。
guest

0

ベストアンサー

CSVはテキストエディタではなく、Excelで管理を行いたい

そのため敢えてダブルクォーテーションで囲まずにCSVを出力してみました

PoC実装の進め方として、順番が逆ではないかと。
Excelの仕様はユーザが制御できないので「Excel側が受領可能な書式のCSVを、システムがインポート/エクスポートできるようにする」やり方でないといけません。

また「システム側からExcelで扱える形式としてエクスポート」は一番最後にすべきです。
一般的に層や境界をまたぐ際の変換処理は、それぞれの層で都合の良い形式が決まってからです。

というわけで、PoC実装の進め方としては以下のようにするとよいと思います。

  1. Excel側のみでの確認
    1. 取り扱う予定のHTMLソース(改行・クォーテーション含む)を直接Excelのセルで入力し、CSV形式で保存
    2. 保存したcsvファイルをExcelで開き直して、元のまま正しいHTMLソースで取得できることを確認
      ※この際、csvファイルが内部でどのような形式(エスケープなど)で記述されているかは、Excel上で編集する人には関係がないはず
  2. システム側のみでの確認
    1. 取り扱う予定のHTMLソースをDBに直接保存し、通常のHTMLエスケープ処理(所謂サニタイジング)をすっ飛ばして画面にHTML要素として表示できることを確認

境界をまたぐ変換部分(csv入出力、DB入出力)は一般的なPHPライブラリやAPIとかを使えばよいので、変換処理とかの自力実装で悩むようなことはあまりないのではないでしょうか。
実際のcsv書式としては既出の他の方の回答にある通りになると思います

ただcsvのライブラリは普通にRFC4180準拠であれば問題ないとは思うのですが、Excelのcsv形式はRFC準拠してないとかいう説もあるので一応確認した方がよいかもです。
(まあ日本語環境ならあまり問題ないとは思いますが…)

投稿2024/08/13 14:55

編集2024/08/13 14:57
pecmm

総合スコア647

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

smaeda

2024/08/15 07:20

ご回答いただきありがとうございました。 分かりやすく記載いただいたおかげで、確認すべきポイントが整理できました。 結局、下記仕様で出力を行う事にしました。 ・カンマ区切りかつダブルクォートで列を囲む ・DB内のダブルクォートはエスケープして テキストエディタで開くと、HTML内のダブルクォートはエスケープされた状態となりますが、 Excelで開くと機転を利かせてくるのか、HTML内のダブルクォートはエスケープされず、生のHTMLを貼り付けて保存する事ができました。
guest

0

回答ではありません

phpでもVB.NETでもなく、dockerが動作するLinux上python3で書かれた、ORMであるSQLAlchemyとデータ解析支援ライブラリのpandasを使用した実験コード(shell script)を置いておきます。想定DBはSQL Serverではなく、sqlite3/mysql/postgresqlの3つです。

空のディレクトリで実行すると、dockerを使用してデータベースを構築し、ITEM_MASTERテーブルを作成、中に2つだけレコードを作って、その中身をcsvにダンプしています。ダンプしている部分だけのコード(shell scriptの実行で生成されるdump_csv_sqlite3.py)であれば、

python

1from sqlalchemy import create_engine 2from sqlalchemy.orm import Session 3from sqlalchemy.ext.automap import automap_base 4import pandas as pd 5DATABASE = 'sqlite:///db.sqlite3' 6Base = automap_base() 7engine = create_engine( 8 DATABASE, 9 echo=True 10) 11Base.prepare(engine, reflect=True) 12ItemMaster = Base.classes.ITEM_MASTER 13with Session(engine) as session: 14 query = session.query(ItemMaster) 15 df = pd.read_sql(str(query), session.bind) 16 df.to_csv('data_sqlite3.csv',index=False)

これだけですよ(コード上ITEM_MASTERが商品マスタのテーブル名)。ちゃんと正しくエスケープされたCSVを吐くと思いますし、HTML部分はそのカラムの型に応じて最良の方法で出力されると思います。.xlsxで吐くようなことも簡単な変更で出来るでしょう。大量のデータをそのまま扱うことはできないかもしれませんが、検討される上で、普通どうするんだろう?というような部分は、ある程度参考になるかもしれません。

一応言っておくと、よく分からないのに本番環境で使う、というのは絶対やめましょう。業務でそんなことをしたら怒られるだけではすみません(クビが飛ぶ上に場合によっては損害賠償請求されます)。

bash

1set -eux 2if [ -d env ]; then 3 . env/bin/activate 4else 5 python3 -m venv env 6 . env/bin/activate 7 pip install -U pip setuptools 8 pip install SQLAlchemy pandas mysql-connector-python psycopg2-binary 9fi 10DB_ROOT_PASSWORD=my-secret-pw 11cat >start_mysql.sh <<EOF 12docker run -d --rm --name mysql -v $(pwd)/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=$DB_ROOT_PASSWORD -p 3306:3306 mysql 13docker exec -i mysql bash <<EOF2 14while ! mysql -uroot -p"$DB_ROOT_PASSWORD" </dev/null 2>/dev/null;do 15 sleep 1 16done 17EOF2 18EOF 19cat >start_postgres.sh <<EOF 20docker run -d --rm --name postgres -v $(pwd)/postgres:/var/lib/postgresql/data -e POSTGRES_PASSWORD=$DB_ROOT_PASSWORD -p 5432:5432 postgres 21docker exec -i postgres bash <<EOF2 22while ! psql --username postgres </dev/null 2>/dev/null;do 23 sleep 1 24done 25EOF 26cat >stop_mysql.sh <<EOF 27docker stop mysql 28EOF 29cat >stop_postgres.sh <<EOF 30docker stop postgres 31EOF 32for db in sqlite3 mysql postgres; do 33 case $db in 34 sqlite3) 35 constr='sqlite:///db.sqlite3' 36 ;; 37 mysql) 38 constr="mysql+mysqlconnector://root:${DB_ROOT_PASSWORD}@localhost/mysql" 39 ;; 40 postgres) 41 constr="postgresql://postgres:${DB_ROOT_PASSWORD}@localhost/postgres" 42 ;; 43 esac 44 cat >create_data_$db.py <<EOF 45from sqlalchemy import create_engine, Column, Integer, BigInteger, String, Numeric, UnicodeText 46from sqlalchemy.orm import DeclarativeBase,sessionmaker 47class Base(DeclarativeBase): 48 pass 49""" 50商品マスタ 51""" 52class ItemMaster(Base): 53 __tablename__ = 'ITEM_MASTER' 54 item_id = Column('item_id', Integer, primary_key=True, autoincrement=True, comment='商品ID') # sqlite3でautoincrementにするにはIntegerにする必要がある 55 jan_code = Column('jan_code', String(13), comment='JANコード', nullable=True) 56 isbn_code = Column('isbn_code', String(13), comment='ISBNコード', nullable=True) 57 model_number = Column('model_number', String(100), comment='型番', nullable=True) 58 item_name = Column('item_name', String(100), comment='商品名') 59 purchase_price = Column('purchase_price', Numeric(20,2), comment='仕入価格') 60 purchase_lot_id = Column('purchase_lot_id', BigInteger, comment='購入ロットID', default=0) 61 supplier_id = Column('supplier_id', BigInteger, comment='サプライヤーID', default=0) 62 lead_time_id = Column('lead_time_id', BigInteger, comment='リードタイムID', default=0) 63 sales_channel_id = Column('sales_channel_id', BigInteger, comment='販売チャンネルID', default=0) 64 html_code = Column('html_code', UnicodeText(), comment='HTMLコード', default=0) 65DATABASE = '$constr' 66engine = create_engine( 67 DATABASE, 68 echo=True 69) 70Base.metadata.create_all(engine) 71Session = sessionmaker( 72 autocommit = False, 73 autoflush = False, 74 bind = engine 75) 76with Session.begin() as session: 77 item = ItemMaster() 78 item.jan_code = '4901990028929' 79 item.item_name = 'やきそば弁当' 80 item.purchase_price = 100.00 81 # https://www.maruchan.co.jp/products/search/205405.html より引用 82 item.html_code = '''\ 83<table><tbody> 84<tr><th>希望小売価格</th> <td>236 円(税抜価格)</td></tr> 85<tr><th>内容量</th> <td>132g(めん100g)</td></tr> 86<tr><th>リニューアル日</th><td>2019年02月04日</td></tr> 87<tr><th>JANコード</th> <td>4901990028929</td></tr> 88<tr><th>販売エリア</th> <td>北海道</td></tr> 89</tbody></table> 90''' 91 session.add(item) 92 item = ItemMaster() 93 item.isbn_code = '9780141354828' 94 item.item_name = 'Charlotte\'s Web' 95 item.purchase_price = 1442.00 96 # https://www.amazon.co.jp/Charlottes-Web-Puffin-Book-White/dp/0141354828/ より引用 97 item.html_code = '''\ 98<p><span>'From grammar to the tenderness in which this story is delivered, E. B. White's writing is so perfect... 99And Garth William's muted illustrations are entirely without fault. Whether read aloud or solo, this is a book well deserving of it's "classic" status.' - </span> 100<span class="a-text-italic">The Children's Book Review</span> 101<span><br><br>A poignant, humorous story of a pig, a spider and a little girl.<br> 102Wilbur the pig's life has already been saved by Fern, but when he is sold to her uncle, he realises his life is in even more danger. 103Enter Charlotte A. Cavatica, a beautiful large grey spider. Charlotte is determined to keep Wilbur from the chopping block, 104and comes up with an ingenious way to do just that.</span></p>\ 105''' 106 session.add(item) 107 session.commit() 108EOF 109 cat >dump_csv_$db.py <<EOF 110from sqlalchemy import create_engine 111from sqlalchemy.orm import Session 112from sqlalchemy.ext.automap import automap_base 113import pandas as pd 114DATABASE = '$constr' 115Base = automap_base() 116engine = create_engine( 117 DATABASE, 118 echo=True 119) 120Base.prepare(engine, reflect=True) 121ItemMaster = Base.classes.ITEM_MASTER 122with Session(engine) as session: 123 query = session.query(ItemMaster) 124 df = pd.read_sql(str(query), session.bind) 125 df.to_csv('data_$db.csv',index=False) 126EOF 127 if [ -f start_$db.sh ]; then sh -eux start_$db.sh;fi 128 python create_data_$db.py 129 python dump_csv_$db.py 130 if [ -f stop_$db.sh ]; then sh -eux stop_$db.sh;fi 131done 132deactivate

あと、最後になってしまいましたが、SQL Serverであれば付属のコマンドであるbcpでcsvを扱えたと思います。できることは限られますが、速度も申し分ないはずですよ。

投稿2024/08/13 21:17

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

smaeda

2024/08/15 08:45

ベストアンサーは別の方を選ばせていただきましたが、コードまで記載いただきありがとうございました。 「bcpでcsvを扱う」という件も、調べてみようと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問