コンピュータや音楽の事書いてます

MW_WP_Form にURL投稿禁止機能をつける

wp-content/plugins/mw-wp-form/classes/validation-rules/class.url.php
というファイルがある。これはURLを入力してほしい時のルールである。
単純に考えて、これの条件を逆にすればURL禁止ができる。
class.url.phpをコピーして、class.nourl.php とする。

クラス名を変更: Urlの手前にnoをつけた

class MW_WP_Form_Validation_Rule_noUrl extends MW_WP_Form_Abstract_Validation_Rule {

nameも

	protected $name = 'nourl';

条件に ! をつけ、 ^ を外した。メッセージを相応しいものに書き換える。

		if (! preg_match( '/https{0,1}:\/\/[^\/]+\.[^\.]+/', $value ) ) {
			'message' => __( 'URL の投稿は禁止です.', 'mw-wp-form' ),

'URL'を'noURL'に変更

		<label><input type="checkbox" <?php checked( $value[ $this->get_name() ], 1 ); ?> name="<?php echo MWF_Config::NAME; ?>[validation][<?php echo $key; ?>][<?php echo esc_attr( $this->get_name() ); ?>]" value="1" /><?php echo esc_html_x( 'noURL', 'validatioin', 'mw-wp-form' ); ?></label>

そうすると、WordpressのMW WP Formのバリデーションルールの中にこれが現れるのでチェックを入れる。

エラーの時、該当箇所までスクロールしてほしいので、
wp-content/plugins/mw-wp-form/js/form.js
の最後の } ); の手前に下記を挿入。

  var e = $('.error');
  if ( e.length > 0 ) {
    var position = e[0].parentNode.offsetTop - 100; 
    var prop = {scrollTop:position};
    $('body,html').delay(200).animate(prop, 600, 'swing');
  }

シェルの挙動や表示のカスタマイズ

$PROFILE が指し示すファイルを作成or編集し、powershell起動時に設定したいロジックを記載する

例:

Set-PSReadLineKeyHandler -Key Tab -Function Complete #tabキーの挙動をbashの様な感じに
Set-PSReadLineOption -Colors @{ Operator = "ffbb33" } #演算子の色が見にくいので変える

#プロンプトの表記をカスタマイズ
function prompt() {
  # カレント・フォルダのパスから末尾の要素のみを抽出
  "PS " + (Split-Path (Get-Location) -Leaf) + "> "
}

#表示の文字数制限を拡張
$PSDefaultParameterValues["Out-File:Width"] = 1000 # 1000の部分は十分大きな数を適当に

コマンド結果貼り付け時、プロパティ名とか調べてselectとかめんどくさいとき

なんでも | ConvertTo-Html | Set-Clipboard をつければ良い。
一発でクリップボードに入り、Excelに貼り付ければ勝手に表になる。
あとは要らない列を消すだけ。

ls | ConvertTo-Html | Set-Clipboard
Get-Process a* | ConvertTo-Html | Set-Clipboard
Get-Service | ConvertTo-Html | Set-Clipboard

google spreadsheets をダウンロードせずにExcelに読み込む

ワンタッチ更新

google spreadsheetsExcel形式でダウンロードすれば当然Excelで開けるが、元データが更新されたらまたダウンロードしなければならない。Excelには元データが更新されたらワンタッチで更新出来る機能があるが良く使われるのは

  • DBから
  • CSVなどのファイルから
  • Excelファイルから

だが、google spreadsheets からというのは無い。が、「Webから」というのがある。

失敗例

データ→データの取得→その他のデータソースから→Webから
これに https://docs.google.com/spreadsheets/~~~のURLを入力しても、テーブルビューには意味不明な表が表示され、Webビューには「ブラウザを更新して」うんぬんのエラーページが表示されている。

解決するには

「Webから」 の「基本」ではなく、「詳細設定」に

  • HTTP要求ヘッダ
    • User-Agent
  • 右の値に

を入力すると

3つのテーブルが出てきて、

2つ良くわからないテーブルもあるが、目的のテーブルがちゃんとある。
「読み込み」ならExcel、「変換」ならPowerQueryに読み込まれる。
元の表が更新されたときは、Excel側の「更新」をすれば反映される。

配列を一括でExcelに書き込むとき、規則がたくさんある

Range型に代入でいっぺんに書き込める配列の条件:

  • 縦,横の要素数が1で始まっている
  • ジャグド配列ではなく、Object[,]型
  • .Range("A:H") とかだと遅くなるので、きっちり終わりの範囲を示す
  • 要素指定順は[row, column]

下記はlsコマンドの出力から各プロパティをシートに書き出す
苦労した点:

  • 複雑なオブジェクトがあってはならない?ので、"Parent","Root","Directory","Target"を除外した。日付型は大丈夫みたい
  • 少しでも規則に合わないことがあると原因とは無関係そうな感じのエラーをだす
    • 「プログラムの実行を続行するための十分なメモリがありませんでした。」
    • CategoryInfo : OperationStopped: (:) [], OutOfMemoryException
    • + FullyQualifiedErrorId : System.OutOfMemoryException
#実行条件:$sheetがWorksheet型であること
$list=(ls)
$props = $list | Get-Member | where MemberType -in CodeProperty,Property | where Name -notin "Parent","Root","Directory","Target" | select -Unique Name
[object[,]]$arr = [Array]::CreateInstance([Object], (($list.Length+1), $props.Length), (1,1))
$c = 1; foreach($p in $props){
	$arr[1,$c]=$p.Name
	$c++
}
$r = 2; foreach($f in $list){
	$c = 1; foreach($p in $props){
		$arr[$r,$c]=$f.($p.Name)
		$c++
	}
	$r++
}
$a1 = $sheet.Range("a1")
$sheet.Range($a1, $a1.Offset($list.Length,$props.Length-1)) = $arr

まあ、こんなことしなくても
ls | Export-Csv a.csv
で一発なんだけど、、、配列一括代入の方法を確認したかったので。


    
    
  

[Excel] sharepointのExcelパス トラブル解決 FullNameURLEncoded

sharepointExcelパスを加工してHYPERLINK関数でリンクさせようとすると色々とうまくいかない時がある。
こういうやつ https://xxxxx.sharepoint.com/sites/aaa/bbb/Shared%20Documents/~~
シート関数の ENCODEURL() はコロンやスラッシュもエンコードしてしまうので、この場合には使えない。
WorkBookオブジェクトのFullNameURLEncodedは良い感じに必要なところだけをEncodeしてくれているので、VBAPowershellなどでこいつを抽出できれば使える。日本語がガンガン含まれていても問題ないみたい。
シェアポをOnedriveにリンクさせたローカルフォルダ内の*.xlsxであれば、Powershellの場合、
Excelが起動している前提)

using namespace Microsoft.Office.Interop.Excel
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Excel")
$excel = [System.Runtime.InteropServices.Marshal]::GetActiveObject("Excel.Application")
cd シェアポをOnedriveにリンクさせたローカルパス
ls *.xlsx | foreach { 
  $book = $excel.Workbooks.Open($_.FullName); 
  $book.FullNameURLEncoded; 
  $book.Close(); 
}

これで得られたhttp://付きのパスをExcelシートC列に並べた場合、
D列がシート名
E列が"$A$1"などのアドレス
だとすると
=HYPERLINK(CONCAT("[",C1,"]'",D1,"'!",E1))
これでシート指定・アドレス指定のハイパーリンクを作ることが出来た

Excel操作のテンプレ

準備

using namespace Microsoft.Office.Interop.Excel
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Interop.Excel")

これは[Microsoft.Office.Interop.Excel.Range] などを [Range] と省略できるメリットがあるが、名前空間にうるさい人からは怒られるかも?
小規模なスクリプトなら問題ないと思う。

#新規Excelを立ち上げてファイルダイアログで開く場合
$excel = New-Object -ComObject excel.application
$excel.Visible=$true
$book = $excel.Workbooks.Open($excel.GetOpenFilename())
#立ち上げ中のExcelの場合
$excel = [System.Runtime.InteropServices.Marshal]::GetActiveObject("Excel.Application")
$book = $excel.Workbooks(1)

$rがRange型である判定

if($r -is [Range]){ echo Range型である }

$r1, $r2 の共通範囲があるか判定

if($excel.Intersect( $r1, $r2) -ne $null){ echo ある }