スキル棚卸し(2020/5)

スキル棚卸し(2020/5/20)
以下の記事を読んでとても良いと思った人が、現時点での、「自分のできること、できないこと」を正直にリストにまとめみた。という記事をTwitterで見かけたので自分もやってみた

どうやってテクノロジーを追いかけていますか?ジュニアソフトウェア開発者として応募したときにCI/CD、クラウドコンピューティング、Dockerとか大量のことを要求されました。もういっぱいいっぱいです。 - Quora
jp.quora.com


自分の現在のスキルマップとして把握して、今できるできないに限らず、自分の進みたい方向と環境に応じて伸ばしていきたい。

分類は記号をつけた
A
使い方を知っていて、最小限の調査で済むテクノロジー(例:「CI/CDパイプラインのセットアップの仕方を知っている」)
B
企業のインフラで使われていることを知っているテクノロジー(例:「Dockerをいつ、何故使うかは知っている。だけどDockerfileは書いたことがない」)
C
聞いたことはあるけど何者なのか見当がつかないテクノロジー(例:「Kubernetesというのは聞いたことがあるけど、何のために使うのか見当がつかない」)




フロントエンド
A
Javascript
 細かい部分を除いて理解しているが、TypeScriptで書きたい。
TypeScript
 最近あまり触っていないので、本気で書くときにはググりながらになる
 型を意識して書くことで安心感があるので基本的にTypeScriptで書きたい

B
jQurey
 業務で少し使った程度
React
 ほとんど書いたことない。
 4年前、少し触って非同期でレンダリングするテーブルコンポーネントを自作したりした。
Angular
 ほとんど知らない。チュートリアルはやったことある。
node.js
 Expressは少し触ったことがある
 npm用に色々使うイメージが強く、これで何かをするイメージがあまりない
CSS / SASS
 クラスなどを設定して装飾できるのがCSS、SASSはそれをうまく管理できるようにしたものという認識だがSASSは実際に使ったことないのでよく知らない
 FlexBox、Grid Layoutは存在は知ってる
WebPack
 モジュールを管理するときに使うことは知っている
Prettier / Linter関連
 自分で設定を少し変更したくらいであまり使ってない

C
Vue.js
 触ったことない
CSSアニメーション
 アニメーションができることは知っている
 やり方やメリットは知らない
WebGL
 触ったことない

バックエンド
A
Spring
 昔触っていたのである程度は理解している
 最近のものは復習しながらでないと何もできないと思っている
Python
 競馬の機械学習Pythonで実装したのでさまざまなものをフルスクラッチで書くことができる
 テストも実装できる
Java
 さまざまなものをフルスクラッチで書くことができる
C#
 さまざまなものをフルスクラッチで書くことができる

B
WebSocket
 アプリケーションのデモで利用した
Ruby on Rails
 チュートリアルでユーザー管理アプリなどを作った
SQL
 簡単なSQLは使える
 重複レコードの抽出など少し難し目のSQLはググれば作成できる
データベース設計
 複雑なシステムを設計したことがない
 正規化したテーブル設計をすることやインデックスなどを適切に利用することなどは知っている
 データベースはデータ量を考慮した設計をするなどするのは知っている
 ビジネス課題の変化によってデータ量やデータ構造は変わるので最初から最良の設計はできないというイメージがある。
F#
 簡単なCUIアプリケーションを作ったことがある
.Net Framework / .Net Core
 環境に合わせて使うということは知っている
組み込み系 
 Aruduinoでごく簡単なIoTデバイスを制作できる
Go
 Progateのチュートリアルをやった程度
WebAssembly
 Webでネイティブアプリ並のパフォーマンスを発揮できるような技術ということは知っている
機械学習
 競馬の機械学習をやった程度
 Kaggleは使ったことがない
 どういうものに機械学習が向いているのかは分かる
 どういう場合にどういう手法を用いれば最適なのか分からない
認証認可
 Oauth
  セキュリティ対策は詳しくない
  GoogleTwitterなど他サービスのIDを利用してアプリケーションのユーザ認証の代わりにする仕組みという認識
 SSO
  複数サービスで同一IDを利用してログインなどが可能になる仕組みという認識
  Azure ADなどを利用していたが詳しくはない
  ユーザーのグループでの権限管理とかがあるイメージ
 2段階認証
  詳しくない
 ロールの設計
  設定したことがある
設計
 DDD、クリーンアーティクチャ
  名前しか知らない
 デザインパターン
  いくつかは知っている
 Webコンテンツアクセシビリティガイドライン
  アメリカなどで利用するアプリケーションにはしっかりと対応する必要があると聞いたが、対応したことはない
 Swagger
  APIを作成する場合にテスト、API定義の公開などで利用するために少し触った
  詳しくはしらない
 多言語対応
  翻訳は別の人がやっていたため、実際の難しさはよくわかっていない
  アプリケーションやサービス単位のようなある程度大きいくくりで表記ゆれを避ける必要があり、大規模なものであれば専任のチームがあったほうがいいということを前職で感じた
C
C(C言語
 一通り型やメモリ管理などの面倒さを理解している
 ポインタの概念はわかる
 C++を学ぶときに少し復習する程度
C++
 少ししか知らない
 テンプレートというのを聞いたことがあって興味があるが内容を知らない
Kotlin
 JetBrains AcademyのTutorialで勉強中
PHP
 知らない
Elm、Rust、elixir
 名前は知っている

モバイル
C
何もかも触ったことがない
 React Native
 Kotilin
 Swift. Flutter

デスクトップアプリ
A
Eclipse RCP
 利用したアプリケーションを多数作成した
B
.Net Framework
 簡単な計算アプリケーションなどを作成したことがある
C
Unity
 チュートリアルは動かしたことがある
Electron
 名前しか知らない

Azure
Azureについては下記のカテゴリ毎に記載している
https://azure.microsoft.com/ja-jp/services/
A
DevOps
 以前の会社のスクラム開発で活用していた
チーム、個人の権限の管理をしていた
CI / CDパイプラインの作成や管理運用をしていた

B
ID
 以前の会社で複数のアプリケーション間で連携する際にAzure ADの認証を利用していた
 サンプルアプリを自作して連携を確認した
Web
 App ServiceにWebアプリケーションサーバをデプロイし利用していた
 App Service以外は詳しく知らない
コンピューティング
 Virtual Machinesを利用していた
 SSD、かつ良いCPUコアのものを使い通常の開発として利用していた
 Azure FunctionsについてはAzure DevOpsからCI/CDパイプラインの情報を抜き取って一覧化するものを作成した
 それ以外は詳しく知らない
ストレージ
 いくつかのサービスを利用していたが、正確にどれを利用していたかは覚えていない
 非常に簡単に利用できたということは覚えている
コンテナー
 以前の会社で利用しているのは知っていたが、触ることがなかった
 Azure のコンテナーに限らず、Kubernetes、Docker、Containerは使い方、使い勝手を含めて詳細を理解しておきたい
 Containerをうまく扱うためのエンジンがDockerでKubernetesはそのサービスやアプリケーションで複数のContainer同士がうまく連携させるるためのものという認識
セキュリティ
 アプリケーション連携にAzure Active Directoryを利用していた
 ストレージやアプリケーション連携など外部のリソースアクセスの際にAzure Key Vaultを利用していた
 どこまでが外部からアクセスできるかと、開発したアプリケーション間であっても、なんの情報を利用してよいのかという考えが理解されていれば大丈夫だと考えていた
 セキュリティは全般的に知識がないのでクラウドにおいても学習しておきたい
ネットワーク
 設定して利用はしていた
 セキュリティ面でよりよい設定などは完全に理解している
データベース
 Azure SQL Database、Azure Cosmos DBは利用していた
 Azureとはいえ、特に特別な意識なく利用していた
開発者ツール
 Visual Studio, Visual Studio Codeは利用していた
統合
 メッセージングサービスとして利用していた

C
AI + 機械学習
 触ったことがない
Windows Virtual Desktop
 触ったことがない
ハイブリッド環境
 マルチクラウドなどの環境になるほど他社サービスとの連携などをしたことはない
ブロックチェーン
 名前しか知らない
メディア
 趣味で動画配信をしたことがある
モノのインターネット (IoT)
 触ったことがない
モバイル
 触ったことがない
移行
 触ったことがない
管理とガバナンス
 存在は知っている
 実際の本番環境モニタリングはやったことがない
複合現実
 触ったことがない
分析
 触ったことがない

インフラ
A or B
CI/CD
 Jenkins、Azure DevOpsでジョブやジョブを連携するものを作成運用していた
 他のものはよく知らない
Docker
 チュートリアルを見ながら少し動かしたことはある
kubernetes
 コンテナーの運用や連携をやっていくためのものだということしか知らない
Git
 詳しくはないが使っている
 git-flowに則った開発をしていた
チーム開発
 ウォーターフォール開発では要件定義、設計、開発、テスト、運用保守まで一通り経験した
 アジャイル開発もスクラムで行った
スクラム開発
 スクラムマスターの役割での仕事もした
 スクラムマスターの資格はとってない
英語
 インドの開発企業と協力して開発を実施していた
 開発業務において、英語でのコミュニケーションはある程度可能
 細かいニュアンスを伝えたり感じたりするのは難しい

C

Firebase
 名前しか知らない
AWS, Google Cloud Service
 Azureと同様、または近いサービスがあることは知っている
 前職はAzureを使える限り使い、あえてマルチクラウドで運用した方がいい場面がなかったため、詳しくは知らない
IaC
 Teraform、Ansible
  名前だけしかしらない

低レイヤー
A or B
セキュリティ
 XSSCSRF
  対策などを実施したことがあるが、内容を正確に覚えてはない
 SQLインジェクション
  知っている
アルゴリズム
 多少分かる
 AtCoderではまだ茶色
サーバーの設定
 何度も設定した経験はある

C
OS
 詳しくない
アセンブラ
 詳しくない
ミドルウェア
 Nginx
  名前は知っている
 Apache
  設定をした経験はある
TCP/IP
 IPアドレスが何なのか、DNSが何かは分かる
 OSI参照モデルは理解している
 http smtpなどプロトコルがいくつかあるのは知っている
 暗号化周辺の話はよく知らない

ニート生活6ヶ月での気づき

一つ前のエントリが転職の準備をするという記事だったのだけど、結局あの記事を書いたあと、仕事をやめただけで転職活動は進めていない。

転職するよりは、自分の能力ややりたいことを一歩踏み込んで確認しておきたいと思ったのでしばらく仕事なしの状態で自分が何をできるのか確認するため、7月末(最終出社は6/7辺りだったと思う)で仕事をやめるだけやめてみた。

その後、今までに気づいたことを書いていく。

やりたいことはあるか

仕事をやめる前は、会社を作りたいとか、webサービスを作りたいとか考えていたが、結局どれも大変そう(当たり前だけど)と思って特に手をつけずになってしまっている。
自分が本気でやりたいのなら大変かどうかではなく、やるかやらないかの話にしかならないはずなので、結局自分はこれをやりたいわけではないのだと理解できた。

あと、仕事をやめた後は、ゲームをしたりしていたし、なんとなく興味を持って買ったたくさんの技術書を読んだりして過ごしていたので、結局自分は今の時点で死ぬほどやりたいことがあるわけではないのだということを再確認できた。

ただ、学びを得て、それを活かして、社会に貢献できる場があればそれが自分にとっての幸せなのかもしれない、という結論に至った。
そういう場がなければ自分で作った方がいいのではないか、自分で作らないとダメなのではないかという思いで仕事をやめたはずだったのだけど、結局自分はまだそういう場を作りたいとゆるく思うだけで今の時点では本気ではなかったのだろう。

長期の休暇について

実質的にこれを書いている時点で6ヶ月休んでいるわけだけど、この休暇で体や心に変化が起きたのかというとそこまで大きな変化はなかったように思う。

ただ、会社に行かないでいると通勤などで強制的に外出して歩くという行動をしなくなるので、運動不足になりやすく、数ヶ月で数キロ太り、ついに大学生時代の体重からプラス10キロの体重になっていた。
今は運動不足解消のため、筋トレとジョギングをしているが、なかなか体重自体は落ちていない。
筋肉がつくのと脂肪が少しずつ落ちるのとで相殺されている部分もあるのだろう。

精神的な面では、心はだいぶリラックスしているというか、むしろたるんでいるのではないかというくらいにだるだるになっている。
ただ、頭が鈍るのは避けたいと思っていて、結局かなりの頻度というかほぼ毎日プログラミングとか勉強をして過ごしている。

ゲームについて

6月に仕事をやめた後は『SEKIRO』をクリアしようと思っていたし、クリアするまでは他のことをしないと思っていた。
結局1月くらいしたらクリアできてしまって、それからは『MHW』、『ユーロトラックシミュレーター2』、『パワプロ2018』、『Kenshi』、『428 ~封鎖された渋谷で~』などをやっていた。

『SEKIRO』をやるまではアクションで難しそうなゲームはやらないでおこうと思っていたのだけど、SEKIROにしてもMHWにしてもどうやったらうまくなるかを考えつつ、時間をかけて経験を積めば自分でも普通にストーリークリアもできるし、ある程度縛りプレイもできるようになる、ということが分かった。
アクションゲームやシューティングゲームが苦手というのは、単純にそれにかけている時間が短いために経験の絶対値が少ないことと、ゲームやステージを攻略するためのコツを見つけられていないだけだったのか、と気づけたのは良かった。
長年アクションゲームやシューティングゲームは難しくて才能がないのだと思っていたが、これからは少し才能がないと思っても、腰をすえてやってみてから判断しようと思う。

あと、『ユーロトラックシミュレーター2』は以前やっていたことがあって、やめ時がわからず、無限にやってしまうのが分かっていたのに、なぜ新PCにこのゲームをインストールしてしまったのか。。。

自分という人間について

結局自分は大したことのない人間で、能力も一人前くらいでしかないのだということを再認識できた。
自分には才能があり、この才能を世の中に活かすためにはもっと自分にふさわしい場所があるとか、そういう場を自分で作るのだ、ということを思ったとしても実現できないのは自分の意志も能力も全然足りていないことの証明なのだろうと思う。

ただ、仕事をやめる前に考えていた競馬の機械学習はある程度うまくいくようになってきたので、自分の才能は大したことないが、時間をかければそれなりのものにはなるということは分かってよかった。
競馬の機械学習関連についてはまた別の記事で書きたいと思う。

働かずに得る収入について

競馬の機械学習で働かずに収入が得られるようになると、働きたくなってくるという謎の心境の変化があった。
これはなんなのかまだ理解できてないが、働かずに収入を得る方法を究めていってしまうと、社会との接点が少ないのに収入だけ得て生きる形になってしまい、社会との距離感が大きくなることに対する危機感のようなものなのかもしれない。

デイトレーダーの人とか、世の中の高収入で会社などで働いていない人はこの辺りの感覚をどう扱っているのだろうか。少し調べておきたいと思う。


こんな感じで6ヶ月分をまとめると長くなってしまうなと思う。
もっと短く書けるように投稿間隔を短くしたい。せっかくの無職なのだし。

転職準備

久しぶりの転職準備なので、具体的に何をやっていくか考えている。

転職はまだ1度しかやったことがないが、前回はリクルートエージェントを利用させていただいた。
転職する側からするとリクルートエージェントはとても対応がよく、少し高給な採用にはこういう人達が間に入ってくれることによって転職しやすくなるのかと、当時強く思った。

なので、今回もリクルートエージェントだけを利用することを考えようかと思ったが、最近はTwitter転職やLinkedInなどを使って個人で転職先をうまく見つけていく人も多いように見える。
LinkedInなどで、採用される側の興味があったり経験がある分野と会社の欲しい人材とのマッチングがやりやすくなっているのだろう。

なので、そのマッチングの効率を上げるため、また同時にエージェントも利用させていただく場合に自分の考えている内容をまとめておきたい。

採用される側として気になっていることとしては、このあたり。

  • どういう人に来てほしいのか
  • ビジネスの規模、給与レンジ
  • 開発チームが利用している技術
  • 開発チームの関心事(最近の関心事)
  • 開発組織が将来どうなっていきたいのか
  • 開発組織の評価制度

逆に採用する側としても、外国人の新卒採用に関わっていたので、気にかけていたとことはこの辺り。

  • 興味を持っている分野
  • 将来何をしたいか(「技術のスペシャリストとして開発を続けたい」「いつかは技術的なマネジメント方向に進み開発の割合を下げてもよい」「技術のマネジメント方向に進み、経営に関わりたい」「独立して会社を経営したい」など)
  • 今まで何をしてきて、自分が採用されたら何をしたいと考えているのか
  • 人より得意なことや不得意なこと

↑のようなことを考えると、下記については人から見える範囲に書いておいた方がいいのだろうと思う。

  • 自分の関心事
  • 将来において実現したいと考えているもの
  • 自分がやってきたこと、職務履歴
  • 自分の得意なこと不得意なこと

また、関心事と重複する内容だが、やってきたことの中には下記のようなものも書いた方がよいのだろう

  • 次の会社でやりたいこと
  • 今の会社でやれていなかったこと

他にもあればさらに考えるが、今日はこれくらいにして、さっさと職務履歴のような定型的なものを書ききっておこうと思う

PowerShellで中くらいのものを書くときに考えたこと その1

体調不良などがあり、少しブログを書くのを中断してしまったが、また書いていきたいと思う。

今回はPowerShellの話。

今までPowerShellVSTS上のTaskで小さいものを書いていた程度で、特に文法とかコーディングの作法とかを考えずに書いていたが、ある程度の大きさのものを作成しようと思った場合、他人が読んだ場合や自分が半年後に読んだ場合でも、すぐに理解が追い付くようなものにした方がよいと思うのでその辺をどうするか考えたものを書こうと思う。

  1. IDEや環境面
  2. コーディング規約
  3. 外部ファイル化(外部のps1ファイルの関数呼び出し)
  4. スコープ
  5. テスト

IDEや環境面

小さいものを書くのであれば、IDEなどなくとも、メモ帳でもなんでもいいという気持ちだったが、ある程度の大きなものを扱う場合、関数の一覧を見たかったり、コード補完機能が欲しくなったりして結局最終的にVS CodePowerShell拡張機能を追加して開発することにした。
今回はWindows Powershellでの開発をしたかった(Mount-DiskImageなどisoファイルを扱ったりなどがあった)ので、Windows 8.1マシンだったが、下記リンクのWMF5.1を使って、Windows PowerShellのバージョンを5.1に上げておいた。
Installing Windows PowerShell | Microsoft Docs

なお、すべてを理解したわけではないが、Windows PowerShellPowerShell Coreは違うもので、.NET Frameworkと.NET Coreみたいな関係のように見える。
Installing PowerShell | Microsoft Docs
PowerShell CoreにはMount-DiskImageなどの関数がなく、なぜ動かないんだろう・・・?ということで小一時間調べたりした。

コーディング規約

どういう規約でもある程度まともに設定されていればいいと思いますが、基本的にモジュール単位、ファイル単位で統一されたものになっていることが大事だと考えています。
調べたことはこのあたり

すごくいろいろ調べてあって、すごい。全部読みきれなかったが、自分に必要そうな部分を読み取った。
PowerShell のコーディングスタイル - tech.guitarrapc.cóm
また、命名はこのあたり。本家なので、概要から全部読み直してもいい。
PowerShell で用いられる名前の習得 | Microsoft Docs
関数のドキュメントはこのあたり。VSCodeなどのIDEから便利に使えるようにするにはドキュメントも書いておきたいのでここも読んだ。
Windows PowerShell: Build a Better Function | Microsoft Docs


読み取ったのはこのあたり

  • 変数名
    • camelCaseなのかPascalCaseなのか
      • グローバルな変数かローカルな変数かで判断した
      • グローバルな変数はPascalCaseにした
      • ローカルな変数はcamelCaseにした
      • 関数宣言の引数はPascalCaseにした
  • 関数名
    • 今回作成したモジュールでは、すべてデフォルトのスコープ設定にした
    • camelCaseとかPascalCaseではなく、Verb-Nounという形式で書く
      • Verbに設定する単語はGet-Verbsコマンドの一覧から適切なものを利用する
  • 関数ドキュメント
    • 関数の中の先頭に書く

外部ファイル化(外部のps1ファイルの関数呼び出し)

外部ファイルを読みだす場合には、下記のように書いてファイルを読み込むようなコードを追加する

. '.\hoge.ps1'

ただ、上記の記述は実行するパスからの相対参照となるので、仮に↓のような構造にしていた場合、PowerShellコンソールからmain.test.ps1を呼び出して、main.test.ps1の中でmain.ps1を呼び出し、さらにmain.ps1の中で

. '.\hoge.ps1'

とした場合には、hoge.ps1が読み込めません、という意味のエラーメッセージが出力される。
root
 ┣src-dir
 ┃ ┣hoge.ps1
 ┃ ┗main.ps1
 ┗test-dir
   ┣hoge.test.ps1
   ┗main.test.ps1

test用のファイルを上記のように作っているとこういうことになるだけで、Pesterのようなテストツールでテスト用ファイルを自動生成する際にもプロダクトコードと同じ階層に出力されるので、特に問題は発生しないのかもしれない。ただ、もし上記のようなコードでも動くようにするには、関数の中で外部ファイルを相対パスで読み込むような形にする方法があるようだ。

function New-TestFunc ($paramArgs) {
    # ps1読込
    $scriptPath = $script:MyInvocation.MyCommand.Path
    $dirPath = Split-Path -Parent $scriptPath
    $rootPath = Split-Path -Parent $dirPath
    . "$rootPath\src-dir\hoge.ps1"

    # (以下略)
}

変数のスコープとテストについては、別日に書きます。

SonarQubeとVSTSをつなげてカバレッジとか見れるようにする

仕事でSonarQubeとVSTSを連携させた話を書く。

Qiitaなどで、SonarQubeの設定記事はよくあるし、それとJenkinsやその他のCIツールとを連携させている記事は多く見かけるがVSTSと連携させている記事はあまり見かけず、少しつまった部分があったので書いておく。

SonarQubeとは何か

この説明はよくいろいろな記事があるので割愛するが、静的解析ツールの一つ。
SonarQubeを選定した理由としては、静的解析ツールはたくさん色々なものがあるが、オープンソースC#,Typescript,Javascriptなどに対応していて、参考となるドキュメントなどが多いものを調べた結果、検索でたくさんヒットしたり、記事が多かったりしたものをなんとなく選定した。
公式のドキュメントページはこの辺
Documentation - SonarQube Documentation - Doc SonarQube

VSTSとは何か

Visual Studio Team Service
タスク管理からGit、CI/CDまでさまざまなものを幅広く提供しているサービス。これだけを使っておけばASP.NETでの開発は不自由なく進められる。
VSTSを利用している理由は、開発チーム全員にMSのサブスクリプションが割り当てられていて、VSTSを利用できる体制が整っているため、C#で開発するのにVSTSをあえて使わない理由がないので、使っている。

連携設定の方法

VSTS連携設定の方法は比較的簡単で、VSTSからテストなどを実行するための Build Pipeline ( 2018年の途中までは Build Definition という名前だった)の中で、SonarQubeへの連携開始のTaskとSonarQubeへの連携終了のTaskを配置するだけ。

詳しくはここに書いてあって、最初にPrepare Analysis Configuration taskを設定して、ビルド、テストを実行し、Run Code Analysis taskを実行する。もし、Quality Gateを利用したい場合には、Publish Quality Gate Result taskも設定する。

簡単だったのだが・・・

上記までは全然つまらずにSonarQubeのドキュメント通りに進めれば問題なく進められる。
多少つまるとすれば、分析対象のプロジェクトが大きい場合、SonarQube側でOut of Memoryエラーが発生することくらい。
Out of MemoryについてはSonarQubeのドキュメントにも書いてあり環境変数を設定する。
name : SONAR_SCANNER_OPTS
value : -Xmx3072m

ここまでで、大体の作業は終わって、今回あえて記事を書こうと思ったのは、VSTS上のTest Taskが分割されていた場合には、単純に上記の設定ではコードカバレッジの連携がうまくいかないことが分かったためである。

関わっていたプロジェクトでは、順番に依存したテストをかなりの数で書いており、それらが多すぎるとVSTSのエージェント側でもOut Of Memoryとなっていたので、Test Task(C#のテストなので Visual Studio Testという名前のタスク)を分割し計4つのTest Taskを順番に実行していた。
これらをTest1, Test2, Test3, Test4という名前だとする。
VSTSのエージェント側ではTest毎にビルド用フォルダ内に、trxファイルとcoverageファイルが生成される。(Visual Studio Testタスクの中で、Code coverage enabledのチェックをONにしている場合、coverageファイルが生成される)
trxファイルとcoverageファイルはTest Task毎に似たような名前で作成されて、VSTSにアップロード後、次のTest Taskでファイルは上書きされ、差し替えられるようになっている。
そして、最後にRun Code Analysis taskによって、SonarQubeサーバにtrxファイルとcoverageファイルがアップロードされるのだが、Run Code Analysis taskが実行されるタイミングでは、最後のTest4のタスクについてのtrxファイルとcoverageファイルしか残っていないため、すべてのテストについてのテスト結果やcoverageファイルをSonarQubeに連携できないという状態だった。

テスト毎に上書きされるのだから、上書きされないようにファイルを別フォルダに退避させて、Run Code Analysis taskが実行される直前で元の場所に名前を変えるなどして戻して、trxファイル、coverageファイルを4つずつSonarqube側に連携してもらえばよいかと考えたが、どうもRun Code Analysis taskは1回のBuild Pipelineの実行において、trxファイル、coverageファイルともに、1ファイルずつしか扱えないようで、この方法は断念した。

したがって、Sonarqubeに連携するにはどうにかしてtrxファイルとcoverageファイルをマージする必要がある。

trxファイルのマージ

trxファイルのマージはいろいろとググった結果、TRX-Mergerというものがあり、これを使ってマージすることで問題なくなった。

coverageファイルのマージ

coverageファイルのマージもググったのだが、こちらはVisual Studioで用意されているexeを利用すればいいことが分かった。
変換する方法が書いてあるだけだったが、exeから複数のcoverageのファイルパスを並べて実行してしまえば問題なかった。
コマンドは下記のような形
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe" analyze /output:Summary.coveragexml 0.coverage 1.coverage 2.coverage ...


というわけで、書いた大作のpowershellが↓です。
ところどころにGet-Locationと書いてありますが、これはデバッグ用に書いたもので消してないだけなのでうまく無視していください。

前提としてフォルダ構成はこんな感じになっていると思って読んでください。
$(Build.Repository.LocalPath)\TestResults
 ┣previous
 ┃ ┣("HogeAgent-ユニーク名"形式のフォルダ)\In\("ユニーク名"のフォルダ)
 ┃ ┃ ┗.coverageファイル
 ┃ ┣("HogeAgent-ユニーク名"形式のフォルダ)\In\("ユニーク名"のフォルダ)
 ┃ ┃ ┗.coverageファイル
 ┃ ┣("HogeAgent-ユニーク名"形式のフォルダ)\In\("ユニーク名"のフォルダ)
 ┃ ┃ ┗.coverageファイル
 ┃ ┣.trxファイル
 ┃ ┣.trxファイル
 ┃ ┗.trxファイル
 ┃ (↑Test Task毎に生成されているので3つの異なるtrxファイルとcoverageファイルが退避されている)
 ┃ (↓最後のTest Taskによって作成されたtrxファイルとcoverageファイル)
 ┣("HogeAgent-ユニーク名"形式のフォルダ)\In\("ユニーク名"のフォルダ)
 ┃ ┗.coverageファイル
 ┗.trxファイル


.coverageファイルをマージして、一つのcoverage.xmlファイルに変換する
CodeCoverage.exeのパスはVisual Studio 2017用のパスを利用していますが、適宜別のバージョンに読み替えればなんとかなるかと思っています。
※この部分はVSTSPowershell Task (Version 2.*)を利用しています。

cd $(Build.Repository.LocalPath)
# collect coverage file paths
cd TestResults\previous
$targetFilePaths = @()
Get-ChildItem | ForEach-Object -Process {
  # folder name is hard code on each environment ←ここはVSTSのagentの実行者の設定などによって、テスト結果のtrxファイルやcoverageファイルが出力されるフォルダ名が変わるので、こうしています。
  if(($_.Name.StartsWith("HogeAgent") -or $_.Name.StartsWith("HogeAgent2")) -And $_.PSIsContainer){
    $InfolderName = $_.Name + "\In"
    
    cd $InfolderName
# Get-Location
    $coverageFolderName = Get-ChildItem -Name | Select-Object -First 1
    
    cd $coverageFolderName
# Get-Location
    $coverageFileName = Get-ChildItem -Name | Select-Object -First 1
#    $coverageXmlFileName = $coverageFileName + "xml"
    
Write-Output $coverageFileName
#Write-Output $coverageXmlFileName

    # convert to coveragexml
#    & "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe" analyze /output:"$coverageXmlFileName" "$coverageFileName"
    
    $targetFilePath = $InfolderName + "\" + $coverageFolderName + "\" + $coverageFileName
    $targetFilePaths = $targetFilePaths + ,$targetFilePath
    cd ..\..\..
Get-Location
  }
}

# set target merge file
# move to TestResults folder
cd ..
Get-Location
$targetCoverageFilePath = ""
Get-ChildItem | ForEach-Object -Process {
  # folder name is hard code on each environment
  if(($_.Name.StartsWith("HogeAgent") -or $_.Name.StartsWith("HogeAgent")) -And $_.PSIsContainer){
    $InfolderName = $_.Name + "\In"
    
    cd $InfolderName
    $coverageFolderName = Get-ChildItem -Name | Select-Object -First 1
    
    cd $coverageFolderName
    $coverageFileName = Get-ChildItem -Name | Select-Object -First 1

    $targetCoverageFilePath = $InfolderName + "\" + $coverageFolderName + "\" + $coverageFileName
    cd ..\..\..
  }
}

$lastCoverage = [string]$targetFilePaths.Length + ".coverage"
Copy-Item $targetCoverageFilePath -Destination $lastCoverage -Force
For ($i=0; $i -lt $targetFilePaths.Length; $i++) {
  $srcpath = "previous\" + $targetFilePaths[$i]
  $dstpath = [string]$i + ".coverage"
  Copy-Item $srcpath -Destination $dstpath -Force
}

$all_args = @("analyze", "/output:Summary.coveragexml", "0.coverage")
$coverageFiles = ,"0.coverage"
For ($i=1; $i -le $targetFilePaths.Length; $i++) {
  $cov = [string]$i + ".coverage"
  $all_args = $all_args + ,$cov
}
Write-Output $all_args

$cmd = "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Team Tools\Dynamic Code Coverage Tools\CodeCoverage.exe"
& $cmd $all_args

Write-Output $paths


.trxファイルをマージして、一つのtrxファイルに変換する、前にtrxファイルのパスを集めたものをVSTSで利用する変数に格納する
※この部分はVSTSPowershell Task (Version 2.*)を利用しています。

cd $(Build.Repository.LocalPath)
# collect trx file paths
cd TestResults\previous
$targetFilePaths = ""
Get-ChildItem | ForEach-Object -Process {
  if($_.Name.EndsWith(".trx")){
    if($targetFilePaths -eq ""){
      $targetFilePaths = "previous\" + $_.Name
    }
    else{
      $targetFilePaths = $targetFilePaths + "," + "previous\" + $_.Name
    }
  }
}

# set target merge file
# move to TestResults folder
cd ..
Get-Location
Get-ChildItem | ForEach-Object -Process {
  if($_.Name.EndsWith(".trx")){
    $targetFilePaths = $targetFilePaths + "," + $_.Name
  }
}
Write-Output $targetFilePaths

Write-Output ("##vso[task.setvariable variable=TargetFilePaths;]$targetFilePaths")

Write-Output $targetFilePaths
cd ..

.trxファイルをマージして、一つのtrxファイルに変換する
TRX_Merger.exeはビルド後のものを利用しているので、パスがビルドされたものっぽいところになっています。
※この部分だけはVSTSPowershell Taskではなく、Command Line Taskで記述しています。理由はないですが、最初にこのTaskを書こうと思った時に、powershell から exe を叩く際の引数を複数指定する際の呼び方をよく分かっていなかったので、Command Line Taskを使っただけです。

cd $(Build.Repository.LocalPath)\TestResults

$(Build.Repository.LocalPath)\sources\Tools\trx-merger\TRX_Merger\bin\Debug\TRX_Merger.exe /trx:%TargetFilePaths% /output:Summary.trx

del HogeAgent*.trx
del HogeAgent2*.trx

上記によって、Summary.trxとSummary.codecoveragexmlが$(Build.Repository.LocalPath)\TestResultsに出力されているので、このファイルがSonarQubeに連携されるようにVSTSのBuild Pipelineでは、Prepare Analysis Configuration taskにおいて、Advanced > Additional Propertiesのところで、下記の2行を追記する。

sonar.cs.vscoveragexml.reportsPaths=**/Summary.coveragexml
sonar.cs.vstest.reportsPaths=**/Summary.trx

以上で、SonarQubeまでのコードカバレッジの連携がうまくいくようになった。

すごく長いものを書いてしまい、これは2回に分けて書くくらいでもよかったのかもしれないと感じた・・・。

XMLの名前空間

少し前に自社のASP.NETの製品に置いてWeb.configのカスタム部分をCLIで設定できるようにする作業をやっていた。

今回はその際に学んだ(正確には昔Javastrutsとか扱っていた際にも一度学んだような気もする)ものを書いておく。

まず、XDT変換する際に利用するXMLはこのようなものである。

<?xml version="1.0" encoding="utf-8"?>

<!-- web.config 変換の使用方法の詳細については、https://go.microsoft.com/fwlink/?LinkId=125889 を参照してください -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <!-- Remove -->
    <add key="hogeKey" xdt:Transform="Remove" xdt:Locator="Match(key)" />
  </appSettings>
</configuration>

この設定によって、configuration/appSettingsの中のhogeKeyの要素が削除されることになるというのは知っていたが
このxdtであるとかURLとかが何者であるかが分かっていないと、XDT変換用のxmlを生成するプログラムを書こうと思った際に、ドキュメントなどを読んでも、理解が難しかったので、メモをしておきたい。

下記が本当に分かりやすかったので、そのまま読んでおけばいいが、私の知っておきたかった部分だけをメモしておく
XMLにおける名前空間 - データ記述とXML

最初に用語をいくつか確認すると、

<hoge></hoge>

hoge 要素という。

<hoge>  ...  </hoge>

と要素に囲まれた中身をコンテンツという。

<hoge src="img.png" />

と書かれた場合に、これはhogeタグのsrc属性の属性値は"img.png"ということを意味する。

<!-- comment -->

と書かれたものはコメント。


さて、今回私がよく分かっていなかったのは下記の表現である。

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">

xmlnsというのは xml namespaceであり、ここではXML-Document-Transform の名前空間の名前は http://schemas.microsoft.com/XML-Document-Transform で、 これは長いので xdt という別名をつけています。

で、次がこれ。

<add key="hogeKey" xdt:Transform="Remove" xdt:Locator="Match(key)" />

この xdt:TransformというのはXDTで定められたスキーマ内のxdt:Transform属性に"Remove"を設定し、XDTで定められたスキーマ内のxdt:Locator属性"Match(key)"を設定している。

ECMA376のリファレンスを使ってxlsxファイルの中身を見る。

Excel2007から拡張子がxlsx、Office Open XML形式をサポートするようになったこと、xlsxファイルはxmlファイルをzip圧縮したものであることはみなさんご存知だと思います。

しかし、中身のxmlファイルについてはみなさんよく知らないと思いますので、この記事では、その中身について少し読めるようになりみましょう、という内容を書きたいと思います。

中身を読み解くのは簡単です。ECMA376で標準化されているため、立派なリファレンスがあります。現在は4版まで出ており、各版はPart1~Part4まで分けてファイルが存在するため、ECMA-376 4th edition Part 1~ECMA-376 4th edition Part 4を読めば、現在の仕様が分かるということになっています。非常に簡単ですね。

では、リファレンスのpdfを開いて読んでみましょう。
ECMA-376 4th edition Part 1のリンクをクリックして、zipファイルを展開して、PDFを開いて・・・。

・・・

ちょっと、5000ページというのは厳しいですね。

というわけで、方向転換して、ECMA-376のリファレンスと突き合わせながら、Excelで設定した内容とxmlファイルがどう対応しているのかを見て行くという、しょうもないことをやろうと思います。(ここまでが記事の説明)

※なお、少し時間がなく出してしまっているので、誤りがあり可能性があります。
記述内容に誤りがあった場合には訂正させていただきますので、コメントなどで指摘いただければと思います。


というわけで、ここから作業をしていきます。

まず、何も記入していないブックを用意します。

f:id:gototo:20151207143519p:plain

このブックをno-edited.xlsxというファイル名で保存し、拡張子をzipに変更して、展開します。

f:id:gototo:20151207144143p:plain

さて、ようやくxmlファイルが出てきました。
最初の[Content_Types].xmlファイルを見てみましょう。

<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="rels"
    ContentType="application/vnd.openxmlformats-package.relationships+xml" />
  <Default Extension="xml" ContentType="application/xml" />
  <Override PartName="/xl/workbook.xml"
    ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />
  <Override PartName="/xl/worksheets/sheet1.xml"
    ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />
  <Override PartName="/xl/theme/theme1.xml"
    ContentType="application/vnd.openxmlformats-officedocument.theme+xml" />
  <Override PartName="/xl/styles.xml"
    ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />
  <Override PartName="/docProps/core.xml"
    ContentType="application/vnd.openxmlformats-package.core-properties+xml" />
  <Override PartName="/docProps/app.xml"
    ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
</Types>

xmlnsで
http://schemas.openxmlformats.org/package/2006/content-types
を指定しています。
他は。。。rels、xml、...よく分かりませんね。
しかし、なんとなく、Override PartName要素は展開されたファイルパスと合致していそうです。
あ、そうそう、展開したファイルの一覧は↓のようになっています。
/
┣[Content_Types].xml
┣_rels/
┃ ┗.rels
┣docProps/
┃ ┣app.xml
┃ ┗core.xml
┗xl/
  ┣styles.xml
  ┣workbook.xml
  ┣_rels/
  ┃ ┗workbook.xml.rels
  ┣theme/
  ┃ ┗theme1.xml
  ┗worksheets/
    ┗sheet1.xml

どれもぱっと見、よく分からないので、とりあえず、階層が浅いもの→ファイルが少ないフォルダの順に見て行きましょう。
.relsファイルはこうなっています。

<Relationships
  xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId3"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
    Target="docProps/app.xml" />
  <Relationship Id="rId2"
    Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
    Target="docProps/core.xml" />
  <Relationship Id="rId1"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
    Target="xl/workbook.xml" />
</Relationships>

app.xmlとか、core.xmlとか見たことがあるファイルがいますね。
.relsという名前からもこのファイルがzipファイル内の関連を記述しているような感じがあります。

次にapp.xmlです。

<Properties
  xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"
  xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
  <Application>Microsoft Excel</Application>
  <DocSecurity>0</DocSecurity>
  <ScaleCrop>false</ScaleCrop>
  <HeadingPairs>
    <vt:vector size="2" baseType="variant">
      <vt:variant>
        <vt:lpstr>ワークシート</vt:lpstr>
      </vt:variant>
      <vt:variant>
        <vt:i4>1</vt:i4>
      </vt:variant>
    </vt:vector>
  </HeadingPairs>
  <TitlesOfParts>
    <vt:vector size="1" baseType="lpstr">
      <vt:lpstr>Sheet1</vt:lpstr>
    </vt:vector>
  </TitlesOfParts>
  <Company />
  <LinksUpToDate>false</LinksUpToDate>
  <SharedDoc>false</SharedDoc>
  <HyperlinksChanged>false</HyperlinksChanged>
  <AppVersion>15.0300</AppVersion>
</Properties>

この辺りから、少しだけ意味の分かるものが出てきます。まず、Application要素ですが、これは何でしょうか。
Office Open XMLでは、他のofficeソフトも同様にxml形式であるため、Microsoft Excel用のファイルであるということを明示しているのでしょうか。
あと、"ワークシート"という日本語がいきなり出てきたのも気になります。
最後のAppVersionはExcel2013のバージョンで保存したことを表現しているのでしょうか。
この記事を書くのに使用したExcelはExcel2013で、バージョン情報を表示すると、15.0.4771.1000と表示されました。
この辺りで各要素の意味を知りたくなったので、PDF(Ecma Office Open XML Part 1 - Fundamentals And Markup Language Reference.pdf)内で検索してみましょう。
1203ページにある『17.16.5.14 DOCPROPERTY』辺りが定義でしょうか。
MSDN辺りでも検索してみると、下記のようなページがひっかかります。

https://msdn.microsoft.com/ja-jp/library/documentformat.openxml.extendedproperties.scalecrop(v=office.14).aspx

なるほど、ScaleCropはファイルをサムネイル表示するモードなんですかね。ってそんなのあったのか。(ググったらある・・・!)。

では、サムネイル表示されるファイルを作って

f:id:gototo:20151207170632p:plain

ファイルを展開して中身を見てみましょう。

<Properties
  xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"
  xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
  <Application>Microsoft Excel</Application>
  <DocSecurity>0</DocSecurity>
  <ScaleCrop>false</ScaleCrop>
  <HeadingPairs>
    <vt:vector size="2" baseType="variant">
      <vt:variant>
        <vt:lpstr>ワークシート</vt:lpstr>
      </vt:variant>
      <vt:variant>
        <vt:i4>1</vt:i4>
      </vt:variant>
    </vt:vector>
  </HeadingPairs>
  <TitlesOfParts>
    <vt:vector size="1" baseType="lpstr">
      <vt:lpstr>Sheet1</vt:lpstr>
    </vt:vector>
  </TitlesOfParts>
  <Company />
  <LinksUpToDate>false</LinksUpToDate>
  <SharedDoc>false</SharedDoc>
  <HyperlinksChanged>false</HyperlinksChanged>
  <AppVersion>15.0300</AppVersion>
</Properties>

あれ、変わってない!?
ああ、サムネイル表示するモードではなくて、サムネイルが表示モードによって大きいものになったり小さいものになったりするモードのON/OFF表現なんですね。
ただ、それをExcelで設定する方法が分からない。。。これについてはここまでとします。
ScaleCrop以外の要素についてもMSDNには記述されているので、もし必要になったら読むとよさそうです。
https://msdn.microsoft.com/ja-jp/library/documentformat.openxml.extendedproperties(v=office.14).aspx

さて、ScaleCropをtrueにする方法を色々ググったりしていたせいで時間も気力もなくなりつつありますが、
気を取り直して、core.xmlです。

<cp:coreProperties
  xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
  xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/"
  xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <dc:creator>○○ △△</dc:creator>
  <cp:lastModifiedBy>○○ △△</cp:lastModifiedBy>
  <dcterms:created xsi:type="dcterms:W3CDTF">2015-12-07T04:59:38Z</dcterms:created>
  <dcterms:modified xsi:type="dcterms:W3CDTF">2015-12-07T05:00:16Z</dcterms:modified>
</cp:coreProperties>

おや、これはファイルのプロパティの情報のようですね。
各プロパティの内容はEcma Office Open XML Part 2 - Open Packaging Conventions.pdfの41ページ付近に書いてあります。
pdfファイルを見ると、4要素だけではないですね。タイトルやバージョン番号など、様々な要素を設定することができるようです。
そういうば、確かにWindowsでファイルのプロパティ情報を見ても4要素以外にたくさん設定されています。

さて、ここまでエクセルファイルの中身について記述がされていないですね。
ということは残っているxl/フォルダ以下がエクセルファイルの中身(シートの情報など)を表現しているのでしょうきっと。
では、xlフォルダの中身を見ていきます。

まずはxl/styles.xmlです。

<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"
  mc:Ignorable="x14ac">
  <fonts count="2" x14ac:knownFonts="1">
    <font>
      <sz val="9" />
      <color theme="1" />
      <name val="Meiryo UI" />
      <family val="2" />
      <charset val="128" />
    </font>
    <font>
      <sz val="6" />
      <name val="Meiryo UI" />
      <family val="2" />
      <charset val="128" />
    </font>
  </fonts>
  <fills count="2">
    <fill>
      <patternFill patternType="none" />
    </fill>
    <fill>
      <patternFill patternType="gray125" />
    </fill>
  </fills>
  <borders count="1">
    <border>
      <left />
      <right />
      <top />
      <bottom />
      <diagonal />
    </border>
  </borders>
  <cellStyleXfs count="1">
    <xf numFmtId="0" fontId="0" fillId="0" borderId="0">
      <alignment vertical="center" />
    </xf>
  </cellStyleXfs>
  <cellXfs count="1">
    <xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0">
      <alignment vertical="center" />
    </xf>
  </cellXfs>
  <cellStyles count="1">
    <cellStyle name="標準" xfId="0" builtinId="0" />
  </cellStyles>
  <dxfs count="0" />
  <tableStyles count="0" defaultTableStyle="TableStyleMedium2"
    defaultPivotStyle="PivotStyleLight16" />
  <extLst>
    <ext xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
      uri="{EB79DEF2-80B8-43e5-95BD-54CBDDF9020C}">
      <x14:slicerStyles defaultSlicerStyle="SlicerStyleLight1" />
    </ext>
    <ext xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
      uri="{9260A510-F301-46a8-8635-F512D64BE5F5}">
      <x15:timelineStyles defaultTimelineStyle="TimeSlicerStyleLight1" />
    </ext>
  </extLst>
</styleSheet>

styles.xmlはファイル名の通り、書式スタイルを定義しているように見えますね。
また、ここにも"標準"と日本語が設定されています。これはエクセルのリボンにあるスタイルのうち、左上にある文字列を表現しているのでしょうか?
あとは最後のext要素の中身は何を指しているのかよく分かりませんね。

PDF(Ecma Office Open XML Part 1 - Fundamentals And Markup Language Reference.pdf)内で見てみると、1744ページにある『18.8 Styles』辺りが定義のように見えます。
しかし、探すのも読むのも大変ですね。
ここはwebの力を使って、PDF検索より楽なものを探しましょう。
というわけで、↓を使います。

OOXML - Complete documentation and samples

さて、検索が楽になったので、font要素の最初のものを下記を参考に見てみましょう。

OOXML ssml:font - Complete documentation and samples

    <font>
      <sz val="9" />
      <color theme="1" />
      <name val="Meiryo UI" />
      <family val="2" />
      <charset val="128" />
    </font>

フォントサイズが9。
カラーテーマが1。
フォント名はMeiryo UI。
フォントファミリは2。
キャラクタセットは128。
ところどころよく分からないですが、これらもPDFを使ったり、ググったりすればなんとかなりそうな感がありますね。

例えば、キャラクタセットは私はぱっと見で全然分からなかったのですが、PDFを見たところ、Valueに対応した文字コードを使う事が分かります。
で、今回のものは128。つまり0x80*1shift_jisのようです。

フォントファミリはPDF(18.18.94 ST_FontFamily (Font Family)の項)を見て、
Romanを指定しているということが分かります。
なんとなく、こうやっていくと大抵のものはなんとかなりそうですね。

もう時間がないので、さっさと行きます。
次にxl/workbook.xmlです。

<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
  mc:Ignorable="x15">
  <fileVersion appName="xl" lastEdited="6" lowestEdited="6"
    rupBuild="14420" />
  <workbookPr defaultThemeVersion="153222" />
  <mc:AlternateContent
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <mc:Choice Requires="x15">
      <x15ac:absPath
        xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac"
        url="C:\Users\USERNAME\Desktop\ecma作る\" />
    </mc:Choice>
  </mc:AlternateContent>
  <bookViews>
    <workbookView xWindow="0" yWindow="0" windowWidth="10065"
      windowHeight="3480" />
  </bookViews>
  <sheets>
    <sheet name="Sheet1" sheetId="1" r:id="rId1" />
  </sheets>
  <calcPr calcId="152511" />
  <extLst>
    <ext xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
      uri="{140A7094-0E35-4892-8432-C4D2E57EDEB5}">
      <x15:workbookPr chartTrackingRefBase="1" />
    </ext>
  </extLst>
</workbook>

これはファイルパスやアプリケーションの情報を保存しているxmlファイルでしょうか。
xWindow="0" yWindow="0" windowWidth="10065" windowHeight="3480"
などの値はwindowサイズのように見えます。このようなものも保存してあるのですね。
詳細は省略します。

次はxl/_rels/workbook.xml.relsです。

<Relationships
  xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId3"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
    Target="styles.xml" />
  <Relationship Id="rId2"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
    Target="theme/theme1.xml" />
  <Relationship Id="rId1"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
    Target="worksheets/sheet1.xml" />
</Relationships>

xmlファイルがそれぞれどういう役割をしているかを記述しています。


次はxl/theme/theme.xmlです。

<Relationships
  xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="rId3"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
    Target="styles.xml" />
  <Relationship Id="rId2"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
    Target="theme/theme1.xml" />
  <Relationship Id="rId1"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet"
    Target="worksheets/sheet1.xml" />
</Relationships>

xmlファイルがそれぞれどういう役割をしているかを記述しています。

<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
  name="Office テーマ">
  <a:themeElements>
    <a:clrScheme name="Office">
      <a:dk1>
        <a:sysClr val="windowText" lastClr="000000" />
      </a:dk1>
      <a:lt1>
        <a:sysClr val="window" lastClr="FFFFFF" />
      </a:lt1>
      <a:dk2>
        <a:srgbClr val="44546A" />
      </a:dk2>
      <a:lt2>
        <a:srgbClr val="E7E6E6" />
      </a:lt2>
      <a:accent1>
        <a:srgbClr val="5B9BD5" />
      </a:accent1>
      <a:accent2>
        <a:srgbClr val="ED7D31" />
      </a:accent2>
      <a:accent3>
        <a:srgbClr val="A5A5A5" />
      </a:accent3>
      <a:accent4>
        <a:srgbClr val="FFC000" />
      </a:accent4>
      <a:accent5>
        <a:srgbClr val="4472C4" />
      </a:accent5>
      <a:accent6>
        <a:srgbClr val="70AD47" />
      </a:accent6>
      <a:hlink>
        <a:srgbClr val="0563C1" />
      </a:hlink>
      <a:folHlink>
        <a:srgbClr val="954F72" />
      </a:folHlink>
    </a:clrScheme>
    <a:fontScheme name="Office">
      <a:majorFont>
        <a:latin typeface="Calibri Light" panose="020F0302020204030204" />
        <a:ea typeface="" />
        <a:cs typeface="" />
        <a:font script="Jpan" typeface="MS Pゴシック" />
        <a:font script="Hang" typeface="?? ??" />
        <a:font script="Hans" typeface="宋体" />
        <a:font script="Hant" typeface="新細明體" />
        <a:font script="Arab" typeface="Times New Roman" />
        <a:font script="Hebr" typeface="Times New Roman" />
        <a:font script="Thai" typeface="Tahoma" />
        <a:font script="Ethi" typeface="Nyala" />
        <a:font script="Beng" typeface="Vrinda" />
        <a:font script="Gujr" typeface="Shruti" />
        <a:font script="Khmr" typeface="MoolBoran" />
        <a:font script="Knda" typeface="Tunga" />
        <a:font script="Guru" typeface="Raavi" />
        <a:font script="Cans" typeface="Euphemia" />
        <a:font script="Cher" typeface="Plantagenet Cherokee" />
        <a:font script="Yiii" typeface="Microsoft Yi Baiti" />
        <a:font script="Tibt" typeface="Microsoft Himalaya" />
        <a:font script="Thaa" typeface="MV Boli" />
        <a:font script="Deva" typeface="Mangal" />
        <a:font script="Telu" typeface="Gautami" />
        <a:font script="Taml" typeface="Latha" />
        <a:font script="Syrc" typeface="Estrangelo Edessa" />
        <a:font script="Orya" typeface="Kalinga" />
        <a:font script="Mlym" typeface="Kartika" />
        <a:font script="Laoo" typeface="DokChampa" />
        <a:font script="Sinh" typeface="Iskoola Pota" />
        <a:font script="Mong" typeface="Mongolian Baiti" />
        <a:font script="Viet" typeface="Times New Roman" />
        <a:font script="Uigh" typeface="Microsoft Uighur" />
        <a:font script="Geor" typeface="Sylfaen" />
      </a:majorFont>
      <a:minorFont>
        <a:latin typeface="Calibri" panose="020F0502020204030204" />
        <a:ea typeface="" />
        <a:cs typeface="" />
        <a:font script="Jpan" typeface="MS Pゴシック" />
        <a:font script="Hang" typeface="?? ??" />
        <a:font script="Hans" typeface="宋体" />
        <a:font script="Hant" typeface="新細明體" />
        <a:font script="Arab" typeface="Arial" />
        <a:font script="Hebr" typeface="Arial" />
        <a:font script="Thai" typeface="Tahoma" />
        <a:font script="Ethi" typeface="Nyala" />
        <a:font script="Beng" typeface="Vrinda" />
        <a:font script="Gujr" typeface="Shruti" />
        <a:font script="Khmr" typeface="DaunPenh" />
        <a:font script="Knda" typeface="Tunga" />
        <a:font script="Guru" typeface="Raavi" />
        <a:font script="Cans" typeface="Euphemia" />
        <a:font script="Cher" typeface="Plantagenet Cherokee" />
        <a:font script="Yiii" typeface="Microsoft Yi Baiti" />
        <a:font script="Tibt" typeface="Microsoft Himalaya" />
        <a:font script="Thaa" typeface="MV Boli" />
        <a:font script="Deva" typeface="Mangal" />
        <a:font script="Telu" typeface="Gautami" />
        <a:font script="Taml" typeface="Latha" />
        <a:font script="Syrc" typeface="Estrangelo Edessa" />
        <a:font script="Orya" typeface="Kalinga" />
        <a:font script="Mlym" typeface="Kartika" />
        <a:font script="Laoo" typeface="DokChampa" />
        <a:font script="Sinh" typeface="Iskoola Pota" />
        <a:font script="Mong" typeface="Mongolian Baiti" />
        <a:font script="Viet" typeface="Arial" />
        <a:font script="Uigh" typeface="Microsoft Uighur" />
        <a:font script="Geor" typeface="Sylfaen" />
      </a:minorFont>
    </a:fontScheme>
    <a:fmtScheme name="Office">
      <a:fillStyleLst>
        <a:solidFill>
          <a:schemeClr val="phClr" />
        </a:solidFill>
        <a:gradFill rotWithShape="1">
          <a:gsLst>
            <a:gs pos="0">
              <a:schemeClr val="phClr">
                <a:lumMod val="110000" />
                <a:satMod val="105000" />
                <a:tint val="67000" />
              </a:schemeClr>
            </a:gs>
            <a:gs pos="50000">
              <a:schemeClr val="phClr">
                <a:lumMod val="105000" />
                <a:satMod val="103000" />
                <a:tint val="73000" />
              </a:schemeClr>
            </a:gs>
            <a:gs pos="100000">
              <a:schemeClr val="phClr">
                <a:lumMod val="105000" />
                <a:satMod val="109000" />
                <a:tint val="81000" />
              </a:schemeClr>
            </a:gs>
          </a:gsLst>
          <a:lin ang="5400000" scaled="0" />
        </a:gradFill>
        <a:gradFill rotWithShape="1">
          <a:gsLst>
            <a:gs pos="0">
              <a:schemeClr val="phClr">
                <a:satMod val="103000" />
                <a:lumMod val="102000" />
                <a:tint val="94000" />
              </a:schemeClr>
            </a:gs>
            <a:gs pos="50000">
              <a:schemeClr val="phClr">
                <a:satMod val="110000" />
                <a:lumMod val="100000" />
                <a:shade val="100000" />
              </a:schemeClr>
            </a:gs>
            <a:gs pos="100000">
              <a:schemeClr val="phClr">
                <a:lumMod val="99000" />
                <a:satMod val="120000" />
                <a:shade val="78000" />
              </a:schemeClr>
            </a:gs>
          </a:gsLst>
          <a:lin ang="5400000" scaled="0" />
        </a:gradFill>
      </a:fillStyleLst>
      <a:lnStyleLst>
        <a:ln w="6350" cap="flat" cmpd="sng" algn="ctr">
          <a:solidFill>
            <a:schemeClr val="phClr" />
          </a:solidFill>
          <a:prstDash val="solid" />
          <a:miter lim="800000" />
        </a:ln>
        <a:ln w="12700" cap="flat" cmpd="sng" algn="ctr">
          <a:solidFill>
            <a:schemeClr val="phClr" />
          </a:solidFill>
          <a:prstDash val="solid" />
          <a:miter lim="800000" />
        </a:ln>
        <a:ln w="19050" cap="flat" cmpd="sng" algn="ctr">
          <a:solidFill>
            <a:schemeClr val="phClr" />
          </a:solidFill>
          <a:prstDash val="solid" />
          <a:miter lim="800000" />
        </a:ln>
      </a:lnStyleLst>
      <a:effectStyleLst>
        <a:effectStyle>
          <a:effectLst />
        </a:effectStyle>
        <a:effectStyle>
          <a:effectLst />
        </a:effectStyle>
        <a:effectStyle>
          <a:effectLst>
            <a:outerShdw blurRad="57150" dist="19050" dir="5400000"
              algn="ctr" rotWithShape="0">
              <a:srgbClr val="000000">
                <a:alpha val="63000" />
              </a:srgbClr>
            </a:outerShdw>
          </a:effectLst>
        </a:effectStyle>
      </a:effectStyleLst>
      <a:bgFillStyleLst>
        <a:solidFill>
          <a:schemeClr val="phClr" />
        </a:solidFill>
        <a:solidFill>
          <a:schemeClr val="phClr">
            <a:tint val="95000" />
            <a:satMod val="170000" />
          </a:schemeClr>
        </a:solidFill>
        <a:gradFill rotWithShape="1">
          <a:gsLst>
            <a:gs pos="0">
              <a:schemeClr val="phClr">
                <a:tint val="93000" />
                <a:satMod val="150000" />
                <a:shade val="98000" />
                <a:lumMod val="102000" />
              </a:schemeClr>
            </a:gs>
            <a:gs pos="50000">
              <a:schemeClr val="phClr">
                <a:tint val="98000" />
                <a:satMod val="130000" />
                <a:shade val="90000" />
                <a:lumMod val="103000" />
              </a:schemeClr>
            </a:gs>
            <a:gs pos="100000">
              <a:schemeClr val="phClr">
                <a:shade val="63000" />
                <a:satMod val="120000" />
              </a:schemeClr>
            </a:gs>
          </a:gsLst>
          <a:lin ang="5400000" scaled="0" />
        </a:gradFill>
      </a:bgFillStyleLst>
    </a:fmtScheme>
  </a:themeElements>
  <a:objectDefaults />
  <a:extraClrSchemeLst />
  <a:extLst>
    <a:ext uri="{05A4C25C-085E-4340-85A3-A5531E510DB2}">
      <thm15:themeFamily
        xmlns:thm15="http://schemas.microsoft.com/office/thememl/2012/main"
        name="Office Theme" id="{62F939B6-93AF-4DB8-9C6B-D6C7DFDC589F}" vid="{4A3C46E8-61CC-4603-A589-7422A47A8E4A}" />
    </a:ext>
  </a:extLst>
</a:theme>

ここに来て、長いファイルですね。。。
心が少し折れそうになりましたが、中身は単純に見えます。
これはExcelのテーマですね。私のExcelにはこんなにも多くのテーマが設定されていたのか。

さて、いよいよ最後のファイルです。xl/worksheets/sheet1.xmlは下記のようになっています。

<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac"
  mc:Ignorable="x14ac">
  <dimension ref="A1" />
  <sheetViews>
    <sheetView tabSelected="1" workbookViewId="0" />
  </sheetViews>
  <sheetFormatPr defaultRowHeight="12" x14ac:dyDescent="0.2" />
  <sheetData />
  <phoneticPr fontId="1" />
  <pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75"
    header="0.3" footer="0.3" />
</worksheet>

おお、これはシートの情報ですね。
シート名がない?と思いましたが、xl/workbook.xmlに記述してあります。
dimension情報から、初期フォーカス一をA1にしていること、
sheetView情報からシートタブが選択状態にあるという情報が読み取れます。
他はシートのデフォルト情報ですね。
デフォルト行高さ、
デフォルト列幅、
フォント、
印刷ページのマージン

以上で、ようやく空のファイルの情報を読み取ることが出来ました。
本当はこの後に、ファイルをExcelを使用せずに作成してみれば、どういう要素がどういう関連を持って、
設定されているのかがよく分かるのですが、それは別の場所で書こうと思います。

最後に、なぜこんな重いテーマをこの12/7に書こうと思ったかという説明を少しだけ書こうと思います。
ECMA-376というのは説明なしで記述していますが、この初版は2006の12/7に出ているのです。

f:id:gototo:20151208004234p:plain
(https://en.wikipedia.org/wiki/Office_Open_XML)

というわけで、

ハッピーバースデー ECMA-376!

9歳の誕生日おめでとう!

(日付は変わってしまっていますが、まだアメリカ時間とかだと12/7の筈なのでセーフ)

業務アプリケーションはExcelと切っても切り離せない関係になってしまっているので
Office Open XMLがなくなることは今後もそうそうないでしょう。
私達に仕事をさせてくれるXMLの仕様に感謝をこめてこの記事を終わりたいと思います。

*1:10進数→16進数は(数字) to hex。16進数→10進数は(16進数) to decimalでググるのが便利です。