ExcelでWebの挿絵を書く

はじめに

Webに載せる挿絵を書く時、みなさんはどんなツールを使ってますか?

私はExcelを使ってます。こんな仕組みになってます。

Excel挿絵システム

このシステムの利点は、ビットマップ系のファイルとDraw系のファイルがいつも一緒に関連付けられて管理されていることだと思う。 Webの挿絵を手直ししたくても、Draw系のファイルが残ってないというような悲劇が起きない。

ExcelのHTML形式で保存した時のファイル群をさぐる

まずは、ExcelファイルをHTML形式で保存した時のファイルの構成を見てみよう。

画像ファイルへの道筋

さきほどのファイル群から画像ファイルへ至る方法を説明しよう。

というわけで、HTMLファイルから各ワークシートへのリンクと<img>タグを見つけるスクリプトが必要だ。まず、これを作ってみよう。

HTMLファイルから必要な情報を得るスクリプト

正規表現を使えば簡単に情報は取り出せる。

まずはライブラリ。

  # excel_images.rb
  def get_subhtml_list(html_text)
    subhtml_list = []
    tag_list = html_text.gsub(/\r|\n/,"").scan(/<link\s+.*?>/)
    tag_list.each {|linktag|
      if linktag =~ /id=\"shLink\"/
        if linktag =~ /href=\"(.*?)\"/
          subhtml_list.push $1
        end
      end
    }
    return subhtml_list
  end
  
  def get_imgtag_list(html_text, dirname)
    imgtag_list = []
    tag_list = html_text.gsub(/\r|\n/,"").scan(/<img\s+.*?>/)
    tag_list.each {|imgtag|
      if (imgtag =~ /src=(.+?)\s/) and (imgtag =~ /alt=\"(.+?)\"\s/)
        (imgtag =~ /src=(.+?)\s/)
        img_filename = File.join(dirname, $1)
        (imgtag =~ /alt=\"(.+?)\"\s/)
        img_keyname = $1
        imgtag_list.push [img_keyname, img_filename]
      end
    }
    return imgtag_list
  end
  

実行スクリプト。

  # analize_excel_html.rb
  
  require 'excel_images'
  
  filename = ARGV.shift
  html_text = open(filename).read
  subhtml_list = get_subhtml_list(html_text)
  
  subhtml_list.each {|sub_html_filename|
    puts "**** #{sub_html_filename}"
    dirname = File.dirname(sub_html_filename)
    html_text = open(sub_html_filename).read
    imgtag_list = get_imgtag_list(html_text, dirname)
    p imgtag_list
  }
  

これを実行すると、こんな結果になる。sample.htmは先ほどExcelで作ったサンプルファイル。

  $ ruby analize_excel_html.rb sample.htm
  **** sample.files/sheet001.htm
  [["image_sample", "sample.files/image002.png"]]
  **** sample.files/sheet002.htm
  [["image_sample2", "sample.files/image003.png"]]
  **** sample.files/sheet003.htm
  []
  

画像を取り出すスクリプト

今回、目標としているのはCGIで画像を取り出すことだが、そのためには、WebサーバでRubyのCGIが利用できる必要がある。 さらに、Webサーバに直接Excelからファイルが保存できる必要もある。

このような環境は、イントラネットや自宅サーバでないとなかなか用意できないだろうから、まずExcelの保存フォルダから 画像ファイルを別フォルダに移すスクリプトを書いてみる。保存時のファイル名はExcel上で画像につけた名前を使う。

画像ファイルの保存

先ほど作ったexcel_images.rbも使う。 このスクリプトを使うと、ExcelImageFilePathに保存されているExcelファイルで示される画像ファイルをEXT_DIRNAMEに保存できる。

  #Ruby -Ks
  # ext_imgfiles.rb
  require 'excel_images.rb'
  
  
  def extract_file(img_name, source_filename)
    source_filename =~ /\.(\w+?)$/
    extname = $1
    #extname = File.extname(source_filename)
    basename = File.basename(source_filename)
    dest_filename = File.join(EXT_DIRNAME, img_name+"."+extname)
    source_file = open(source_filename)
    dest_file = open(dest_filename, "w")
    dest_file << source_file.read
    dest_file.close
    source_file.close
  end
  
  EXT_DIRNAME = "/home/www/html/images"       # 画像ファイルの出力先
  ExcelImageFilePath = "/home/www/html/xxxxx"  # Excelファイルの置き場
  
  excel_filelist = Dir.glob(File.join(ExcelImageFilePath,"*.htm"))
  excel_filelist.each {|filename|
    p filename
    html_text = open(filename).read
    subhtml_list = get_subhtml_list(html_text)
    subhtml_list.each {|sub_html_filename|
      dirname = File.dirname(sub_html_filename)
      html_text = open(sub_html_filename).read
      imgtag_list = get_imgtag_list(html_text, dirname)
      imgtag_list.each {|imgtag|
        img_name = imgtag[0]
        excel_imgfilepath = imgtag[1]
        extract_file(img_name, excel_imgfilepath)
      }
    }
  }
  

CGIで画像を参照するスクリプト

CGIを使って、直接Excelの保存先フォルダから画像を抜き出し、Webブラウザに画像データを渡してみよう。

CGIにはパラメータとして、画像につけた名前を指定する。それを元に、Excelが出力した画像ファイルを探し出し、ファイル内容を そのままブラウザに返してやれば画像が表示されるようだ。

このCGIを利用するには、CGIからExcelが出力したファイル群にアクセスする必要があるため、Sambaも動作させておく必要がある。 ExcelImageFilePathにExcelファイルの保存ディレクトリ名を入れておき、以下のような<img>タグで挿絵を読み出せる。

  <img src="/cgi-bin/imageref.rb?tag=excel_img_flow" alt="Excel挿絵システム" />
  

もちろん、この例ではexcel_img_flowが画像につけられた名前である。

このCGIの欠点は、リクエストがあるたびに毎回、Excelが出力したHTMLファイルを渡り歩いて画像ファイルを探すため、絵が 増えてくると動作が遅くなる、ということか。

まぁ、これは先に対応テーブルを作っておき、CGI実行時には対応テーブルを使って画像ファイルを探すようにすればいい。これは またの機会に。

  #!/usr/local/bin/ruby
  require "cgi"
  require 'excel_images'
  
  
  def show_image(excel_imgfilepath)
    excel_imgfilepath =~ /\.(\w+?)$/
    extname = $1.downcase
    case extname
    when "jpg"
      output_data = "Content-type: image/jpeg\n\n"
    when "png"
      output_data = "Content-type: image/png\n\n"
    when "gif"
      output_data = "Content-type: image/gif\n\n"
    when "tiff"
      output_data = "Content-type: image/tiff\n\n"
    else
      output_data = "Content-type: image/jpeg\n\n"
    end
  
  
    fn = open(excel_imgfilepath)
    img_dat = fn.read
    fn.close
    output_data << img_dat
    return output_data
  end
  
  def find_image(tagname)
    excel_filelist = Dir.glob(File.join(ExcelImageFilePath,"*.htm"))
    excel_filelist.each {|filename|
      html_text = open(filename).read
      subhtml_list = get_subhtml_list(html_text)
      subhtml_list.each {|sub_html_filename|
        sub_html_filename = File.join(ExcelImageFilePath, sub_html_filename)
        dirname = File.dirname(sub_html_filename)
        html_text = open(sub_html_filename).read
        imgtag_list = get_imgtag_list(html_text, dirname)
        imgtag_list.each {|imgtag|
          img_name = imgtag[0]
          excel_imgfilepath = imgtag[1]
          if img_name == tagname
            return show_image(excel_imgfilepath)
          end
        }
      }
    }
    return nil
  end
  
  
  ExcelImageFilePath = "/home/www/html/xxxx"  # Excelファイルの置き場
  
  input = CGI.new
  tagname = input["tag"].shift
  if tagname then
    print find_image(tagname)
  end
  

ライセンス

ライセンスはRubyのライセンスに従います。

Copyright (C) 2003 Oka Yasushi <yac@tech-notes.dyndns.org>

You may redistribute it and/or modify it under the same license terms as Ruby.

免責事項

本プログラムは無保証です。作者は、プログラム自身のバグ、あるいは、本プログラムの実行など から発生するいかなる損害に対しても責任を持ちません。

変更履歴

2003/12/14

Initial Release


*1複数のワークシートに図がないと、結果がかなり 違ってきてしまうんです。