- 投稿日:2020-01-24T18:53:14+09:00
【C#】NPOIを使って「.xls」の外部参照URLを無視する方法
概要
- C# をつかって「.xls」拡張子のエクセルファイルを書き込むが、参照できないURLがbookに含まれているときの処理について
使用バージョン
- .NETFramework 4.6.1
- NPOI 2.4.1
やりたいこと
- 一括で「.xls」ファイルに入っている指定のセルの書き込みをする
- 例:sheet1のC3に数字を書き込む
- "=sheet1!C3" と書かれているセルがあり、セルの内容を反映(セルの評価)したい
適用Source
var book = WorkbookFactory.Create(@"C:\sample.xls"); var sheet = book.GetSheet(XlsxSheet.SheetName); //ブック全体の数式を評価 book.GetCreationHelper().CreateFormulaEvaluator()bookWriter.EvaluateAll();エラーがおきる
- 以下エラー
- NPOI.Util.RuntimeException:Could not resolve external workbook name... NPOI.SS.Formula.Workbook.NotFoundException: Could not resoleve external workbook name...
推測される原因
- Excelの機能で、セルに対して他のファイルから読み取ったセルを代入することができるが そのファイルパスが参照できない、開けない状態。
対策
var book = WorkbookFactory.Create(@"C:\sample.xls"); var sheet = book.GetSheet(XlsxSheet.SheetName); var bookWriter = book.GetCreationHelper().CreateFormulaEvaluator(); //外部参照URLを無視 bookWriter.IgnoreMissingWorkbooks = true; //ブック全体の数式を評価 bookWriter.EvaluateAll();所感
- NPOIってJavaのPOIから移行してるってこともあり、POIのリファレンスをみると分かる
- ただNPOIとPOIは移行とはいえ、メソッドの名前やクラスの名前がイコールではないため、コピペは不可。
- ググっても「ignore」を使っている人がいなかったで上げてみました。初投稿です。誰かのためになれば幸いです。
- 投稿日:2020-01-24T18:44:34+09:00
VSCodeでC#のインテリセンスが効かないとき
プロジェクトを開いたときに右下にこれが出る。
このとき、Output の
OmniSharp Log
に下記のメッセージが出る。
Microsoft.Build.Exceptions.InvalidProjectFileException: 指定された SDK 'Microsoft.NET.Sdk' は見つかりませんでした。何が起きているか
OmniSharp(C#のインテリセンス) が使う MSBuild のバージョン?があっていない。
環境変数で、OmniSharp の使う MSBuild を指定する
.NETCore-3.1 で動かす例
MSBuildSDKsPath=C:\Program Files\dotnet\sdk\3.1.100\Sdks
(PATHに注意。マイナーバージョンちがうなどC:\Program Files\dotnet\sdk\3.1.101\Sdks
)設定してから、VSCode を再起動してエラーが無くなれば成功。
逆にUnityなどで .NET-4.7 などを対象にする場合は動かなくなるかもしれぬ。OmniSharpの設定(~/.ominisharp/omnisharp.json)
{ "MsBuild": { "MSBuildSdksPath": "c:/Program Files/dotnet/sdk/3.1.101/Sdks" } }これはうまくいかなかった。書き方が違うのかもしれない。
https://github.com/OmniSharp/omnisharp-vscode/issues/3074
関連
- https://h.s64.jp/entry/omnisharp_msbuild_2017_conflict
- https://qiita.com/Densyakun/items/42515bb3e5e8b1b8cb7f
上記の記事では、Visual Studio Build Tools 2017 のアンインストール や Visual Studio をインストールするにより、MSBuild のインストール状況が変わるので間接的に解決していると思われる。
MSBuildは、.NETSdk や VisualStudio に付属しているものが知らない間にインストールされることがあるので、OmniSharp が適切なMSBuildを発見できなくなることがありそう。逆に環境変数
MSBuildSDKsPath
が間違って動かない場合もある。
- 投稿日:2020-01-24T16:47:21+09:00
visual stdio データ入力されたものをグラフ化する
睡眠時間と満足度をユーザーに入力してもらい、それをグラフ化したいのですがプログラムのコードの書き方が分かりません。
教えてください。
- 投稿日:2020-01-24T12:34:17+09:00
UniRxでダブルクリック判定を3種類の方法で書いてみる
UnityのUniRxは便利ですし、ネットの記事を読むことで基本的な事は理解できるでしょう
しかし、いざ応用するとなるとなかなか感覚を掴めませんそこで、ダブルクリック判定は、UniRxの扱いを入門するのにちょうどいいものだと思い、
UniRxによるシングル、ダブルクリック判定法を3つ書いてみました今回実装するダブルクリック判定の仕様は次のようです
・シングルクリックとダブルクリックをどちらも判定できる
・ダブルクリック時に、シングルクリックは判定しない
・連打時の事も考える準備
まずはクリック判定だけ取っておきましょう
var click = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0));先に言っておきます。シングルとダブルの判定は同じObservable内でbool型で判定します
シングルクリックならfalseを流し
ダブルクリックならtrueを流すことにします1つ目
まずは、ネットで
UniRx ダブルクリック
など検索するといくらか目にする例ですvar dClick1 = click .TimeInterval() // 前のイベントとの時間差 .Select(v => v.Interval <= TimeSpan.FromSeconds(0.2f)) // ↑ シングルならfalse、ダブルならtrue .Buffer(2, 1) .Where(b => !(b[0] && b[1])); // ↑ 連打時の判定 (3連打以上は無視) // 出力 dClick1.Subscribe(b => Debug.Log(b ? "シングルクリック" : "ダブルクリック"); // ↑ 3項演算子によるシングル、ダブルクリック出力クリックをした時間差で判定する方法ですね
余計に前の状態をBuffer
で取ってこなくてはいけませんが、UniRx初心者が理解しやすい内容と言えます。
連打時の挙動は、
最初にシングルクリック、次にダブルクリックが流れ、
後はまったく流れないです2つ目
今度はストリームの合成の概念を使います
var dClick2 = click .ThrottleFirst(TimeSpan.FromSeconds(0.2f)) // シングルクリック判定の間隔。0.2秒以内に2つ以上流さない .SelectMany(Observable.Return(false) // シングルクリックはfalseを流す .Merge(click // ダブルクリック判定につなげる .Select(_ => true) // ダブルクリックはtrueを流す .Take(TimeSpan.FromSeconds(0.2f)).Take(1))); // ダブルクリック判定。trueを流す今度は、シングルクリック判定をしたら、シングルクリック判定をやめて
ダブルクリック判定を一定時間するという方法です
・Return
により、一旦シングルクリック判定を流し、
・Merge
により、ダブルクリック判定につなげます
・SelectMany
は
元々のObservbleにイベントが流れた時に、
引数に渡したObservableからイベントを取り始めます
ThrottleFirst
によって、シングルクリック判定を一定時間やめておき、
そのうちに、ダブルクリック判定をしています
判定時間を2回指定しなければいけないので少々気持ち悪いです連打時の挙動は
シングルクリックとダブルクリックの判定が交互に流れます
素直な挙動です3つ目
var dClick3 = click .Select(_ => false).Take(1) // シングルならfalse。一つだけ通す .Concat(click.Select(_ => true) // ダブルクリックならtrue .Take(TimeSpan.FromSeconds(0.2f)).Take(1)) // ダブルクリック判定 .RepeatSafe(); // 判定が終わったら繰り返し理解の難易度が高いオペレータを使いますが、一番シンプルな実装方法です
僕はこの方法が一番好きです
Concat
を使っていますがこれは
直前のObservableがOnCompletedしたら、引数に渡したObservableに切り替える
というものです
また、引数を渡さないこともでき、その場合は
直前にSelect
で指定したObservableを使う
(この場合は一時的にIObservable<IObservable<T>>
という型になる)
というようになりますシングルクリック判定が起こってから、
ダブルクリック判定をはじめて、
すべて終了すればRepeatSafe()
により最初から判定を行う
という感じです
RepeatSafe()
はOnCompletedが連続で流れれば繰り返しを終了します
Repeat()
なんて使うな!無限ループが怖いぞ!連打時には
シングルクリックとダブルクリックの判定が交互に行われるので
シングルクリックとダブルクリックが交互に出力されます出力
最後にDebug.Logの出力だけ書きます(1つ目のところでもちらっと書きました)
var doubleClick = dClick3; doubleClick.Subscribe(b => Debug.Log(b ? "ダブルクリック" : "シングルクリック");doubleClickにdClick1や2をいれれば、そちらの方の実装を試せます
最後
ダブルクリックというのは単純なようですが、
実際に判定を取る事を考えると奥が深い処理ですこの記事を書くにあたって、
Concat
を覚えられて良かったですUniRxはまだまだ学習コストが高いですね