jqGrid グリッドデータをクリップボードにコピー

< 画面例 >

1) ナビゲーションボタンにコピーボタンを配置

2) クリックすると全選択 => 選択内容がクリップボードにコピーされる

< コード例 >

1) 呼び出し元


// クリップボードコピー //  
clipCopyButtonJSfunc($("#addrlist"), $("#addrlistpager"), "");

2) コピーボタン追加


**
 * jqGrid table contents copy to clipboard
 * @returns {undefined}
 */
function clipCopyButtonJSfunc(objtable, objpager, idcmpltdmsg) {

  // ==== Clipboard copy ==== //
  $(objtable).jqGrid('navButtonAdd', objpager,
          {
            caption: 'Copy',
            //id: "copygmapdest",
            title: "Copy table contents",
            onClickButton: function () {
              //alert($(this).attr("id"));
              selectDomElm(this);

              // 選択しているテキストをクリップボードにコピーする
              document.execCommand("Copy");
              // 選択の解除 //
              //window.getSelection().removeAllRanges();


            },
          }
  );


}

3) 指定DOMエレメント選択


// 指定DOMエレメント選択 //
function selectDomElm(obj) {
  // Rangeオブジェクトの取得
  var range = document.createRange();
  // 範囲の指定
  range.selectNodeContents(obj);

  // Selectionオブジェクトを返す。ユーザが選択した範囲が格納されている
  var selection = window.getSelection();
  // 選択をすべてクリア
  selection.removeAllRanges();
  // 新規の範囲を選択に指定
  selection.addRange(range);
}

ここで教えていただきました : https://9-bb.com/javascript-3/

jqGrid サブグリッドの表示非表示をプロパティでセット

jqGrid の最近のアップデートのドキュメントを見ていたら、ありましたので、早速実装してみました。

前は、loadComplete でグリッドデータをループして、クラスをセットしていたので、すっきりわかりやすくなりました。

isHasSubGrid: で出来ます。



 // ######### サブグリッド ######### //
 subGrid: true,
 isHasSubGrid: function (rowid) {   // <=== New from 5.3
   // if custommerid begin with B, do not use subgrid
   var cell = $(this).jqGrid('getCell', rowid, "cnt_img");
   //console.log(cell, rowid);
   if (cell && cell == 0) {    // <=== === は使えない
     return false;
   }
   return true;
 },
 subGridOptions: {
   // configure the icons from theme rolloer
   plusicon: "ui-icon-triangle-1-e",
   minusicon: "ui-icon-triangle-1-s",
   openicon: "ui-icon-arrowreturn-1-e"
 },
 subGridRowExpanded: showChildGrid,    // <=== 展開した時の処理
 // ######### サブグリッド ######### //     

MySQL 半角カナ => ひらがな変換関数

 

 

 

半角カタカナが読みにくいので、ひらがなに変換するUDFを作ってみました。
濁音、半濁音は2文字になります。

パ => は°
バ => は″

ので、下に置いた変換関数をかますと正しく変換されます。

CREATE DEFINER=`root`@`localhost` FUNCTION `fc_hankana2hira`(
	`hankana` VARCHAR(200)
)
RETURNS varchar(200) CHARSET utf8
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN

DECLARE RESTXT VARCHAR(200) DEFAULT '';
DECLARE CFG_HANKANA VARCHAR(100) DEFAULT '';
DECLARE CFG_HIRA VARCHAR(100) DEFAULT '';
DECLARE LEN_HANKANA SMALLINT DEFAULT 0;
DECLARE POS SMALLINT;
DECLARE CUR_HANKANA CHAR(1);
DECLARE CUR_CFGPOS SMALLINT;
DECLARE CUR_HIRA CHAR(1);


SET CFG_HANKANA = 
'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲンァィゥェォャュョッ゙゚(). -_[]1234567890';
SET CFG_HIRA = CONCAT(
'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろ',
'わをんぁぃうぇぉゃゅょっ″°(). -_[]1234567890'
);


SET LEN_HANKANA = CHAR_LENGTH(hankana);
SET POS = 1;

WHILE POS <= LEN_HANKANA DO
	
	SET CUR_HANKANA = MID(hankana, POS, 1);
	SET CUR_CFGPOS = LOCATE(CUR_HANKANA, CFG_HANKANA);
	SET CUR_HIRA = MID(CFG_HIRA, CUR_CFGPOS, 1);
	
	SET RESTXT = CONCAT(RESTXT, CUR_HIRA);
	

  SET POS = POS + 1;
END WHILE;



RETURN fc_hankanazen_dakuon_modify(RESTXT);

END
CREATE DEFINER=`root`@`localhost` FUNCTION `fc_hankanazen_dakuon_modify`(
	`hiraorg` VARCHAR(200)

)
RETURNS varchar(200) CHARSET utf8
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT '半角カナから全角ひらがな変換した後の濁音半濁音補正'
BEGIN

DECLARE RESTXT VARCHAR(200) DEFAULT '';

SET RESTXT =
  REPLACE(
  REPLACE(
  REPLACE(
  REPLACE(
  REPLACE( 
  REPLACE(
	REPLACE(
	REPLACE(
	REPLACE(
	REPLACE(
	hiraorg, 
	'か″', 'が'),
	'き″', 'ぎ'),
	'く″', 'ぐ'),
	'け″', 'げ'),	
	'こ″', 'ご'),
	
	'さ″', 'ざ'),	
	'し″', 'じ'),
	'す″', 'ず'),	
	'せ″', 'ぜ'),
	'そ″', 'ぞ'
	); 

SET RESTXT =
  REPLACE(
  REPLACE(
  REPLACE(
  REPLACE(
  REPLACE( 
  REPLACE(
	REPLACE(
	REPLACE(
	REPLACE(
	REPLACE(
	RESTXT, 
	'た″', 'だ'),
	'ち″', 'ぢ'),
	'つ″', 'づ'),
	'て″', 'で'),	
	'と″', 'ど'),
	
	'は″', 'ば'),	
	'ひ″', 'び'),
	'ふ″', 'ぶ'),	
	'へ″', 'べ'),
	'ほ″', 'ぼ'
	); 
	
SET RESTXT =
  REPLACE(
	REPLACE(
	REPLACE(
	REPLACE(
	REPLACE(
	RESTXT, 

	
	'は°', 'ぱ'),	
	'ひ°', 'ぴ'),
	'ふ°', 'ぷ'),	
	'へ°', 'ぺ'),
	'ほ°', 'ぽ'
	); 	


RETURN RESTXT;

END

 

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

MySQL即効クエリチューニング【電子書籍】[ yoku0825 ]
価格:1980円 (2022/12/22時点)

楽天で購入

 

 

Yahoo!スタティックマップAPI で市区町村塗分け

まだ試してないので、コード例はありません。

Google Charts で都道府県塗分けが出来たので、市区町村も試してみたくなったので、調べたら、Googleでは出来なくて、Yahoo でできるようです。

APIドキュメント : https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/static.html

Java リフレクションを使って同じメソッド名があるクラスを指定して実行する

リフレクションは昔、JDBCのドライバーを使う時、データベース別にクラスを違える為、class.forName() を使ったくらいで、その便利さが活用できぬままでしたが、同じメソッド名で異なる処理してるクラスを選んでインスタンス化 => メソッド実行とかできると楽で便利なので、ちょっと調べて実装してみました。

< コード例 >


package mapaddress;

import java.util.ArrayList;
import java.io.File;
import java.io.*;

import java.util.*;
import java.lang.reflect.Method;
import java.lang.reflect.Executable;
import java.lang.reflect.AccessibleObject;

public class MapAddress {

  public static void main(String[] args) {

    // 引数がない場合、すぐ終わらす //
    if (args.length == 0) {
      System.out.println("no argument");
      return;
    }

    // このクラスのパッケージ名 //
    String packageName = MapAddress.class.getPackage().getName();
    System.out.println(packageName);

    // 引数はクラス名の1個 //
    String nmClass = args[0];
    System.out.println(args[0]);

    MapAddress MA = new MapAddress();

    try {
      // クラスオブジェクト取得 //
      Class<?> c = Class.forName(packageName + "." + nmClass);

      // インスタンス化 //
      Object objc = c.newInstance();

      // 第一メソッド実行 //
      Method method = c.getMethod("getAddressPage");
      method.invoke(objc);

      // 第ニメソッド実行 //
      if (MA.is2methodMap.get(nmClass)) {
        method = c.getMethod("addStoreDetails");
        method.invoke(objc);
      }

      // 生成されたリストをデバッグ //
      method = c.getMethod("getStoreDtlList");
      System.out.println(method.invoke(objc));

      // ???????? なので各クラスのメソッドにする //
      //ArrayList<HashMap<String, String>> dtllist = method.invoke(objc);
      
      // 引数がある場合は、getMethodで定義しておく //
      method = c.getMethod("execUpdateTable", String.class, String.class);
      method.invoke(objc, MA.listnameMap.get(nmClass), iconfnm);
      

    }
    catch (Exception e) {
      e.printStackTrace();
    }

  }
  
}


ここらで教えて頂く :

https://www.sejuku.net/blog/33252

https://itsakura.com/java-reflect

http://pppurple.hatenablog.com/entry/2016/07/23/205446

https://www.logicbig.com/how-to/code-snippets/jcode-reflection-class-getmethod.html

MySQL LOAD DATA LOCAL INFILE で特定列を指定してインポートする

郵政事業庁の郵便番号CSVを自分の MySQL のテーブルにインポートすることになり、必要な列だけを選べないかと探してたところ、(今まで MySQL のバルクインサートでは、全列そのまんまインポートしかしたことがなかったので)

CSVの列指定は、 @1, @3, @6 とかで、列位置指定

MySQL は、

SET
JIS_ORG = @1,
ZIP_ORG = @3,
K_NAME = @9,

とかでマッピングします。

LOAD DATA LOCAL INFILE '/????/?????.csv'
INTO TABLE mst_zip
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
(@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15)
SET 
JIS_ORG = @1,
ZIP_ORG = @3,
K_NAME = @9,
H_NAME_ORG = @6,
K_JIS = @8,
H_JIS_ORG = @5
;

ここで教えていただきました : http://jigsaw.hatenablog.jp/entry/2013/06/12/113016

[商品価格に関しましては、リンクが作成された時点と現時点で情報が変更されている場合がございます。]

3ステップでしっかり学ぶMySQL入門改訂2版 [ 山田祥寛 ]
価格:2728円(税込、送料無料) (2022/12/22時点)

GoogleMap API ジオコーダーを Java で使う

Javascript からの Geocorder の利用が、1回で連続して変換できるのが 10件 に制限されているので、大量データの変換に不向きなので、調べて実装しました。



package mapaddress.dbupdate;

import java.util.*;
import java.io.*;

import com.google.maps.GeoApiContext;
import com.google.maps.*;
import com.google.maps.model.GeocodingResult;
import com.google.maps.model.LatLng;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import org.apache.ibatis.session.SqlSession;

//import com.google.maps.GeoApiContextBuilder;
/**
 * GoogleMap API ジオコーダー用クラス
 */
public class Geocorder {

  /**
   * プロキシ設定
   */
  private final String PROXY_HOST = "?????????";
  private final int PROXY_PORT = 0;

  private final String API_KEY = "???????????????????????????????";

  private GeoApiContext context;

  private String addr;
  private double lat;
  private double lon;
  private String zip = "";

  /**
   * デフォルトコンストラクタ
   */
  public Geocorder() {
    context = new GeoApiContext.Builder()
            .apiKey(API_KEY)
            .build();
  }

  /**
   * APIキー指定コンストラクタ
   */
  public Geocorder(String apikey) {
    context = new GeoApiContext.Builder()
            .apiKey(apikey)
            .build();
  }

  /**
   * プロキシ用コンストラクタ
   *
   * @param isUseProxy
   */
  public Geocorder(boolean isUseProxy) {

    if (isUseProxy) {
      SocketAddress addr = new InetSocketAddress(this.PROXY_HOST, this.PROXY_PORT);
      Proxy proxy = new Proxy(Proxy.Type.HTTP, addr);
      context = new GeoApiContext.Builder()
              .apiKey(API_KEY)
              .proxy(proxy)
              .build();
    }
    else {
      context = new GeoApiContext.Builder()
              .apiKey("????????????????????????????????????????")
              .build();
    }
  }

  /**
   * @return the addr
   */
  public String getAddr() {
    return addr;
  }

  /**
   * @param addr the addr to set
   */
  public void setAddr(String addr) {
    this.addr = addr;
  }

  /**
   * @return the lat
   */
  public double getLat() {
    return lat;
  }

  /**
   * @param lat the lat to set
   */
  public void setLat(double lat) {
    this.lat = lat;
  }

  /**
   * @return the lon
   */
  public double getLon() {
    return lon;
  }

  /**
   * @param lon the lon to set
   */
  public void setLon(double lon) {
    this.lon = lon;
  }

  /**
   * @return the zip
   */
  public String getZip() {
    return zip;
  }

  /**
   * @param zip the zip to set
   */
  public void setZip(String zip) {
    this.zip = zip;
  }

  /**
   * 正ジオコーダーの実行
   */
  public void execGeoCorder() {

    try {
      GeocodingResult results[] = this.getResults(this.addr);
      //LatLng latLng = results[0].geometry.location; // とりあえず一番上のデータを使う

      if (results != null && results.length > 0) {
        //if (results.length > 0) {
        LatLng latLng = results[0].geometry.location; // とりあえず一番上のデータを使う
        System.out.println("緯度 : " + latLng.lat);
        System.out.println("経度 : " + latLng.lng);
        int len = results[0].addressComponents.length;
        String zip = results[0].addressComponents[len - 1].longName;
        System.out.println("ZIP : " + zip);

        this.lat = latLng.lat;
        this.lon = latLng.lng;
        if (zip != null && !zip.equals("")) {
          this.zip = zip;
        }

      }

    }
    catch (Exception e) {
      e.printStackTrace();
    }

  }

  /**
   * 正ジオコーダー応答取得
   *
   * @param address
   * @return
   * @throws InterruptedException
   * @throws IOException
   */
  public GeocodingResult[] getResults(String address) throws InterruptedException, IOException {

    GeocodingApiRequest req = GeocodingApi.newRequest(context)
            .address(address)
            // .components(ComponentFilter.country("JP"))
            .language("ja");

    try {
      GeocodingResult[] results = req.await();
      if (results == null || results.length == 0) {
        // ZERO_RESULTSはresults.length==0の空配列がsuccessful扱いで返ってくる
        System.out.println("zero results.");
      }
      //results[0].geometry;

      return results;

    }
    catch (Exception e) {
      System.out.println("error.");
      System.out.println(e);
      return null;
    }
  }

  /**
   * 逆ジオコーダーの実行
   */
  public void execRVGeoCorder(String lat_lon) {
    
      try {
      GeocodingResult results[] = this.getRVResults(lat_lon);
      //LatLng latLng = results[0].geometry.location; // とりあえず一番上のデータを使う

      if (results != null && results.length > 0) {
        
        int len = results[0].addressComponents.length;
        String zip = results[0].addressComponents[len - 1].longName;
        System.out.println("ZIP : " + zip);
        this.addr = results[0].formattedAddress.replaceAll("日本、", "");
        System.out.println("ADDR : " + this.addr);
        if (zip != null && !zip.equals("")) {
          this.zip = zip;
        }

      }

    }
    catch (Exception e) {
      e.printStackTrace();
    }


  }

  public GeocodingResult[] getRVResults(String lat_lon) throws InterruptedException, IOException {
    
    

    GeocodingApiRequest req = GeocodingApi.newRequest(context)
            .address(lat_lon)
            // .components(ComponentFilter.country("JP"))
            .language("ja");

    try {
      GeocodingResult[] results = req.await();
      if (results == null || results.length == 0) {
        // ZERO_RESULTSはresults.length==0の空配列がsuccessful扱いで返ってくる
        System.out.println("zero results.");
      }
      //results[0].geometry;

      return results;

    }
    catch (Exception e) {
      System.out.println("error.");
      System.out.println(e);
      return null;
    }
  }

  public static void main(String[] args) {
    
    Geocorder G = new Geocorder(false);  
    G.execRVGeoCorder("31.62457 131.8521498");
    System.out.println(G.addr);
    


  }

}

ここで教えていただきました : http://developers.goalist.co.jp/entry/2017/10/16/150000

逆ジオコーダーも必要あるので、試したところ、Javascript の住所指定と同じく、緯度 + ” ” + 経度 を住所として渡せば出来ました。