Programmer's Note

コード読み書きの備忘録。

JIRAの内容を取ってくるVBA

GPTさん作。

Option Explicit

Sub ExampleUsage()
    Dim issueKey As String
    Dim fieldName As String
    Dim fieldValue As Variant
    Dim strUsername As String
    Dim strApiToken As String
    Dim strURL As String

    ' Replace with your JIRA credentials and URL
    strUsername = "YOUR_USERNAME"
    strApiToken = "YOUR_API_TOKEN"
    strURL = "YOUR_JIRA_URL"

    issueKey = "YOUR_ISSUE_KEY"
    fieldName = "summary"

    fieldValue = GetJiraIssueData(issueKey, fieldName, strUsername, strApiToken, strURL)

    ' Write the result to Excel cells
    Cells(1, 1).Value = fieldName
    Cells(2, 1).Value = fieldValue
End Sub

Function GetJiraIssueData(issueKey As String, fieldName As String, strUsername As String, strApiToken As String, strURL As String) As Variant
    Dim objHTTP As Object
    Dim Json As Object

    Set objHTTP = CreateObject("MSXML2.ServerXMLHTTP.6.0")
    
    ' Build the URL to access the JIRA REST API
    strURL = strURL & "/rest/api/2/issue/" & issueKey
    
    With objHTTP
        .Open "GET", strURL, False
        .setRequestHeader "Content-Type", "application/json"
        .setRequestHeader "Authorization", "Basic " & EncodeBase64(strUsername & ":" & strApiToken)
        .send
        Set Json = ParseJson(.responseText)
    End With

    ' Get the desired field from the JSON response and return its value
    If fieldName = "summary" Then
        GetJiraIssueData = Json("fields")("summary")
    ElseIf fieldName = "status" Then
        GetJiraIssueData = Json("fields")("status")("name")
    ElseIf fieldName = "assignee" Then
        GetJiraIssueData = Json("fields")("assignee")("displayName")
    End If
End Function


Function EncodeBase64(text As String) As String
    Dim arrData() As Byte
    arrData = StrConv(text, vbFromUnicode)

    Dim objXML As MSXML2.DOMDocument60
    Dim objNode As MSXML2.IXMLDOMElement
    
    Set objXML = New MSXML2.DOMDocument60
    Set objNode = objXML
    Set objNode = objXML.createElement("b64")

    objNode.DataType = "bin.base64"
    objNode.nodeTypedValue = arrData
    EncodeBase64 = objNode.Text
    
    Set objNode = Nothing
    Set objXML = Nothing
End Function

久々環境更新。

かっこいいプロンプト表示をしたい。

oh-my-zshを導入したが、Powerlineっぽい表示がまだできていない。

Ricty for Powerline のインストール

参考: 新しいMacを買ったらやること - Qiita

$ brew tap sanemat/font 
$ brew search ricty 
$ brew options ricty 
$ brew install ricty --with-powerline
以下のように怒られたので、
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Preferences or run:
  softwareupdate --all --install --force

$ softwareupdate --all --install --force
を実行
結構時間かかった・・・再起動して完了。
が、もう一回``brew install ricty --with-powerline``やってもだめだったので、

$   sudo rm -rf /Library/Developer/CommandLineTools
$  sudo xcode-select --install

をやって、今度は先に進んだ。

が、Rictyのpowerlineパッチつきフォント使ってみたが、矢印が?になってしまう。 NG。

別のフォントがあることがわかり、こっちを使ってみる。

■HACKGEN 参考:【Bash】ターミナルに矢印を付ける方法を初心者向けに解説する【簡単】 – ブログの設置

brew tap homebrew/cask-fonts
brew install font-hackgen
brew install font-hackgen-nerd

これは、うまく行った。

React NativeのAnimated を試す

React Nativeのアニメーションのテスト。

Animated関連のAPIを使用するようで、この仕組みのイメージが少し分かった。

特定のカーブに従って何かしらの値を変化させて、 その変化をAnimatedなComponentで拾うという感じ。

変化させる値はAnimated.Value()関数で作る。

  percent = new Animated.Value(0);

この値を時間経過によって変化させる。これをアニメーションと言っていて、Animated.timing( ... ).start()を使う。

  startAnime = () => {
    Animated.timing(this.percent, {
      toValue: len,
      duration: 10*1000,
      useNativeDriver: true,
      easing: Easing.linear,
    }).start();
  }

toValueは最終的に持っていきたい値。 durationはどれくらいの時間をかけて変化させるか。msec単位。

iOSの場合useNativeDriver:指定は必須のようで、ないと怒られる。 trueにできない場合もあるので、そのときはfalseで。 easingは値を変化されるカーブを指定できるが、ここではリニアに設定。

あとは、アニメーションさせたい対象。 標準では、

  • Animated.Image
  • Anmated.ScrollView
  • Animated.Text
  • Animated.View
  • Animated.FlatList
  • Animated.SectionList

が用意されている。これらのComponentの任意のpropをアニメーション対象に指定できる、ということのようだ。

さて、ここではsvgライブラリを使ってCircleオブジェクトをアニメーション対象としたい。 この場合は、

const AnimatedCircle = Animated.createAnimatedComponent(Circle);

という風にすれば、Animated 対象となる。

単なるCircleを使ってもだめだった。 Animated.Valueの変化を観察してくれない(つまり、動かない)。

最初は、Animated.Xxxがなぜ必要か分からなかったが、値の変化を拾ってくるかどうか、ということね。

逆に言えば、Animated.createAnimatedComponent()を使えてば、なんでもAnimated対象になるのなら、最強な気がする。

ここではCircle

            strokeDashoffset={this.percent}

というpropがAnimated.Valueを使っている。この値の変化を観察してくれるというわけだ。

以下、全コード。

import React, { Component } from 'react';
import {
  SafeAreaView,
  StyleSheet,
  Button,
  Animated,
  Easing,
} from 'react-native';
import Svg, {
  Circle
} from 'react-native-svg';

const RADIUS = 45;
const len = RADIUS * 2 * Math.PI;
const AnimatedCircle = Animated.createAnimatedComponent(Circle);

class App extends Component {
  percent = new Animated.Value(0);

  startAnime = () => {
    Animated.timing(this.percent, {
      toValue: len,
      duration: 10*1000,
      useNativeDriver: true,
      easing: Easing.linear,
    }).start();
  }

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <Svg height='50%' width='50%' viewBox='0 0 100 100'>
          <Circle
            cx='50'
            cy='50'
            r={`${RADIUS}`}
            stroke='blue'
            strokeWidth='1'
            strokeDasharray={[len, len]}
            strokeDashoffset={this.percent}
          />
          <AnimatedCircle
            cx='50'
            cy='50'
            r={`${RADIUS}`}
            stroke='blue'
            strokeWidth='10'
            strokeDasharray={[len, len]}
            strokeDashoffset={this.percent}
          />
        </Svg>
        <Button title='Start Anime' onPress={this.startAnime} />
      </SafeAreaView >
    );
  }
}

const styles = StyleSheet.create({
  container: {
    justifyContent: 'center',
    alignItems: 'center',
  },
});

export default App;

補足

動作させるには、 https://github.com/react-native-community/react-native-svg が必要で、インストール方法は上記を参照。

Animated.Valueの一番簡単なサンプルは、React Nativeの標準ドキュメントにある。 https://reactnative.dev/docs/animated

参考

https://www.youtube.com/watch?v=Y50CQfyFkGI&t=402s

React Nativeでカメラを使ってみる

React NativeでiPhoneでカメラを使うことができた。以下メモ。

プロジェクトのルートディレクトリを<ProjectRoot>とする。

パッケージのインストール

$ cd <ProjectRoot>
$ npm install react-native-camera --save
$ npx react-native link react-native-camera
$ cd pod
$ pod install

iOSのinfo.plistの編集

<ProjectRoot>ios/の下の、*.xcworkspaceをダブルクリックして、XCodeを起動する。 下記画面のInfoを編集する。

f:id:hifistar:20200825070302p:plain
XCodeのCustom iOS Target Properties

Application requires iPhone environment+をクリックして、リストから Privacy - Camera Usage Descrptionを選んで項目を追加する。 Valueに適当な文字列を入れる。

サンプルコード

いろいろ参考にして作ったサンプルコード。 SNAPボタンで撮って結果を小さいサムネに貼る。 なんかモバイル界隈は変化が速いので、1年後には動かないコードになってそうだけど。 react-nativeのバージョンは4.12.0。

import React, {Component} from 'react';
import {
  SafeAreaView,
  StyleSheet,
  View,
  Button,
  Image,
} from 'react-native';

import {RNCamera} from 'react-native-camera'

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      0: 'https://reactnative.dev/docs/assets/p_cat1.png',
    }
  }

  takePicture = async () => {
    if (this.camera) {
      const options = {quality: 0.5, base64: true}
      const data = await this.camera.takePictureAsync(options)
      console.log(data.uri)
      this.setState({0: data.uri})
    }
  }

  render() {
    return (
      <SafeAreaView style={{flex:1}}>
        <View style={styles.container}>
          <RNCamera
            ref={ref => this.camera = ref}
            type={RNCamera.Constants.Type.back}
            captureAudio={false}
            flashMode={RNCamera.Constants.FlashMode.on}
            style={[{ flex: 8 }, styles.preview]}
          />
          <View style={{ flex: 1, flexDirection: 'row'}}>
            <Image source={{ uri: this.state[0] }} style={styles.thumb} />
            <View style={{flex:2}}>
              <Button
                title='SNAP'
                onPress={this.takePicture.bind(this)}
              />
            </View>
            <View style={{flex: 1}}/>
          </View>
        </View>
      </SafeAreaView>
    )
  }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    justifyContent: 'center',
  },
  preview: {
    justifyContent: 'flex-end',
    alignItems: 'center'
  },
  thumb: {
    flex: 1,
    backgroundColor: 'yellow',
    borderWidth: 1
  }

});

export default App;

React Native公式サイトのpropsを使うサンプルにハマる

ここ2、3日、React Nativeのサンプルを打って動作を確かめている。 なるほど、これは面白いですわ。生産性が高いし流行るはずですわ。

昨日、ちょっとハマったのが以下のコード。

自作のComponentにタグのプロパティを渡す方法についてのサンプルで、Class Componentで書く方法のコードなんだけど、

class Cat extends Component {
  state = { isHungry: true };

  render(props) {
    return (
      <View>
        <Text>
          I am {this.props.name}, and I am
          {this.state.isHungry ? " hungry" : " full"}!
        </Text>

   ...

これ、公式サイトのサンプルをそのまま打ってはいなくて、 適当に書いたテストコードにポイントになる部分を追加するやり方でやってたので、 実際は以下のようなコードになってた。

class Cat extends Component {
  state = { isHungry: true };

  render(props) {
    return (
      <View>
        <Text>
          I am {props.name}, and I am
          {this.state.isHungry ? " hungry" : " full"}!
        </Text>

   ...

何が違うかというと、props.nameというところが、正しくはthis.props.nameじゃないといかんかった。

ちょっと待って、propsってrender()関数の引数やんか。 引数にthisをつけるのおかしいだろ。

と思ったら、引数としてある方がおかしいのでした。 (実際はjavascriptのobjectのpropertyとして定義してある方が、仕組みとしては納得できる)

実際render()関数の引数を外して、

  render() {
    return (
      <View>

にしても動くしね。

ので、公式サンプルの凡ミスでちょっとした時間ハマった。 (かわりにReact Nativeの実装が少し見えた)

なんか気軽にDocumentをEditしてPull Requestできるらしいが、GitHub素人でPRの仕方がわからんので、また後にしよう(笑。

GitHubにあがっているReact Nativeプロジェクトを実行する方法

GitHubに上がっているReact Nativeのプロジェクトをcloneして、 普通にnpx react-native run-iosを実行しても失敗する。

なんだかよくわからないが、色々ググった結果、とりあえず

  1. cloneしたフォルダーに入る
  2. npm iで依存パッケージをダウンロードする
  3. cd ios/
  4. pod install
  5. cd .. して、 npx react-native run-ios

でうまくいった。

謎はあとでわかるようになるのかしら。

参照

Invalid Podfile on Appcenter · Issue #26149 · facebook/react-native · GitHub

React Nativeアプリのバージョン管理

React Nativeのreact-native initでプロジェクトを作ると、ぎょうさんファイルがダウンロードされるけど、バージョン管理するときはどうするんだろ?

必要なファイルしかgitに登録しないはず。 gitは詳しくないので多分勝手に生成される.gitignoreとかの設定だろうなと思いつつ、git連携の仕方が書いてあるブログを探したが、なかなか見つからず。

やっとあったのでメモ↓

How to use Git with React Native. (for Mac users) | by Mike Callahan | React Native Institute | Medium

むちゃくちゃ簡単で、

  1. react-native initでプロジェクトを作成する
  2. フォルダーに入ってgit initgit add .をして、
  3. git commit -m "..."をしたあと、
  4. GitHubリポジトリを作って、git remote add origin master ...して
  5. git push -u origin master

で完了。あとは差分だけadd, commit, pushすればよいと。