Salesforce lightningでReportダウンロード用 URLを作る

 

Salesforce lightningから一旦クラシックモードに変換して、レポートを開く

ReportのURLが下記のよな場合、

https://XXXXXXXX.my.salesforce.com/00O1v000007MXu0

末尾に下記のものをつけて

?isdtp=p1&export=1&enc=UTF-8&xf=csv

結果、以下のようになる。

https://XXXXXXXX.my.salesforce.com/00O1v000007MXu0?isdtp=p1&export=1&enc=UTF-8&xf=csv

ブライ語等の影響で、文字がIndentが右に行ってしまったの対処法(Outlook , Word等)

ベブライ語等の影響で、文字がIndentが右に行ってしまったの対処法

 

少しめんどくさいですが、下記のように対応可能です。

 

  1. Outlookなどから、Wordに対象の文章を貼り付ける
  2. 文章全部を選択(Ctrl+A)
  3. WordのVisual Basicを立ち上げて、Documentに下記のコードを追加して実行

Sub main()

    Application.Run "LtRPara"

    Application.Run "LtRRun"

End Sub

 

  1. 文字が左に戻っているはずなので、Outlook等にコピーして戻す。

SalesforceのReportをCSVでPythonから取得する。

下記のモジュールを使用
github.com

Salesforce lightning

isdtp=p1 と言う記載をclassicより足しておかないと動かない。
URLが少し取得が難しかった(理由:複数のURL表記が有ったため)

import requests
import codecs
from simple_salesforce import Salesforce

site_name = 'Siteの名前を記載してください。'
report_id= 'レポートのIDを記載してください'
password = 'パスワードに置き換えてください。'
username = 'ユーザ名を置き換えてください。'
security_token = 'セキュリティ トークンを置き換えてください。'
filename = r'ファイル名を入れてください。'

sf = Salesforce(username=username, password=password, security_token = security_token)

with requests.session() as s:
    d = s.get("https://%s.salesforce.com/%s?isdtp=p1&export=1&enc=UTF-8&xf=csv"%(site_name,report_id), headers=sf.headers, cookies={'sid': sf.session_id})

text = d.text
sf.session.close()

fp = codecs.open(filename,'w+','utf8')
fp.write(text)
fp.close()

Salesforce classic

isdtp=p1 と言う記載をlightningより削除。

import requests
import codecs
from simple_salesforce import Salesforce

site_name = 'Siteの名前を記載してください。'
report_id= 'レポートのIDを記載してください'。
password = 'パスワードに置き換えてください。'
username = 'ユーザ名を置き換えてください。'
security_token = 'セキュリティ トークンを置き換えてください。'
filename = r'ファイル名を入れてください。'

sf = Salesforce(username=username, password=password, security_token = security_token)

with requests.session() as s:
    d = s.get("https://%s.salesforce.com/%s?export=1&enc=UTF-8&xf=csv"%(site_name,report_id), headers=sf.headers, cookies={'sid': sf.session_id})

text = d.text
sf.session.close()

fp = codecs.open(filename,'w+','utf8')
fp.write(text)
fp.close()

PANDAS 特定カラムにある同じ値のカウントを、現在の表に追加する方法

遅い方法、私のテストデータでは1分かかった

def get_count(x):
    target_column_name = 'Serial Number'
    return len(df[df[target_column_name]==x[target_column_name]].index)
    
df['count'] = df.apply(get_count,axis=1)
df


早い方法
私のテストデータでは1秒もかからなかった

target_column_name = 'Serial Number'
df_temp = df.reset_index().groupby(target_column_name).count().reset_index()[[target_column_name,'index']]
df_merge = pd.merge(left=df,left_on=target_column_name,right=df_temp,right_on=target_column_name,how='left')
df_merge

wxPython RichTextCtrlから画像を取り出す方法

xmlファイルに吐き出して中の画像を取り出しました。

とりあえず私の環境ではpngだった。

imagetype以外は別の処理が必要そうだ。

Imageファイルのヘッダー文字から画像ファイルの種類判定しても良いかもしれない。

 

# -*- coding: utf-8 -*-

###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc
import wx.richtext

# for conv_xml2file
import os
import codecs
import binascii
import hashlib
import xml.etree.ElementTree as ET
try:
	from StringIO import StringIO
except ImportError:
	from io import StringIO

###########################################################################
## conv_xml2py
###########################################################################
def conv_xml2py(xmlpath):
	
	base_dir ,ext = os.path.splitext(xmlpath)
	if not os.path.exists(base_dir):
		os.mkdir(base_dir)

	tree = ET.ElementTree(file=xmlpath)
	md5dat = hashlib.md5()
	line = 0
	img_num = 0
	data = ''
	for item in tree.iter():
		item_type = item.tag.split('}')[1]
		text = item.text
		if text is None :
			text = ''
		text = text.strip()

		if item_type == 'paragraph' :
			line += 1
			if line != 1:
				data += '\n'
		elif item_type == 'text' :
			data += text
		elif item_type == 'data' :
			img_num += 1

			img_bin = binascii.unhexlify(text)
			md5dat.update(img_bin)

			filename = 'img-%06d-%s.png'%(img_num,md5dat.digest().hex())
			img_num += 1

			filepath = os.path.join(base_dir,filename)
			fp = open(filepath,'wb+')
			fp.write( img_bin )
			fp.close()
			data += '"%s"'%(filename)
	filepath_py = os.path.join(base_dir,'aaaa.txt')
	fp_py = codecs.open(filepath_py,'w+','utf8')
	fp_py.write(data)
	fp_py.close()	
	

###########################################################################
## Class MyFrame1
###########################################################################

class MyFrame1 ( wx.Frame ):

	def __init__( self, parent ):
		wx.Frame.__init__ ( \
			self, parent, id = wx.ID_ANY, title = wx.EmptyString, \
			pos = wx.DefaultPosition, size = wx.Size( 500,300 ), \
			style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

		self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )

		bSizer6 = wx.BoxSizer( wx.VERTICAL )

		self.m_button1 = wx.Button( \
			self, wx.ID_ANY, u"MyButton", \
			wx.DefaultPosition, wx.DefaultSize, 0 )
		bSizer6.Add( self.m_button1, 0, wx.ALL, 5 )

		self.m_richText1 = wx.richtext.RichTextCtrl( \
			self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, \
			wx.DefaultSize, \
			0|wx.VSCROLL|wx.HSCROLL|wx.NO_BORDER|wx.WANTS_CHARS )
		bSizer6.Add( self.m_richText1, 1, wx.EXPAND |wx.ALL, 5 )

		self.SetSizer( bSizer6 )
		self.Layout()

		self.Centre( wx.BOTH )

		# Connect Events
		self.m_button1.Bind( wx.EVT_LEFT_DOWN, self.Click_MyButton )

	def __del__( self ):
		pass


	# Virtual event handlers, overide them in your derived class
	def Click_MyButton( self, event ):
		openFileDialog = wx.FileDialog(None, "Open a file", "", "",
			"*.xml", wx.FD_SAVE)

		if openFileDialog.ShowModal() == wx.ID_CANCEL:
			return

		project_path = path = openFileDialog.GetPath() 
		
		handler = wx.richtext.RichTextXMLHandler()
		rt_buffer = self.m_richText1.GetBuffer()
		handler.SaveFile(rt_buffer,project_path)
		conv_xml2py(project_path)


app = wx.App(False)
 
#create an object of CalcFrame
frame = MyFrame1(None)
#show the frame
frame.Show(True)
#start the applications
app.MainLoop()

wxPython RibbonBarの使い方

情報がすごく少ないので、投稿

f:id:dzdaiju:20181125190652p:plain
f:id:dzdaiju:20181125190352p:plain

wxFormBuilder3.9.0から出力されたPythonソースコードには ## PLEASE DO *NOT* EDIT THIS FILE!
とか書いてあるが、残念ながら私の技能ではソース自体修正しないと全くうまく対応出来なかった。

  • wxRibbonBarのwxExpandにチェックをつける

 横幅がRibbonBarがアイコンの位置までしか表示されない事の対策

  • ribbonButtonに適当にIDをつける
  • RibbonButtonBarにイベントを追加(なんのイベントでもOK)

 self.m_ribbonButtonBarMain.Bind( rb.EVT_RIBBONBUTTONBAR_CLICKED, self.click_ribbon_click )
 の様にイベントをrb.EVT_RIBBONBUTTONBAR_CLICKEDにソースレベルで修正

 ID毎にif文で分岐する。
 buttonId = event.GetId()


# -*- coding: utf-8 -*-

###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################

import wx
import wx.xrc
import wx.lib.agw.ribbon as rb

ID_RIBBON_NEW = 1000
ID_RIBBON_OPEN = 1001
ID_RIBBON_SAVE = 1002
ID_RIBBON_RUN = 1003

###########################################################################
## Class TestFrame
###########################################################################

class TestFrame ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"My Tool", pos = wx.DefaultPosition, size = wx.Size( 601,468 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )

        MainSizer = wx.BoxSizer( wx.VERTICAL )

        self.m_ribbonBar = rb.RibbonBar( self , \
			wx.ID_ANY, wx.DefaultPosition, wx.Size( -1,-1 ), wx.lib.agw.ribbon.RIBBON_BAR_DEFAULT_STYLE )
        self.m_ribbonPageMain = rb.RibbonPage( \
			self.m_ribbonBar, wx.ID_ANY, u"Main" , wx.NullBitmap , 0 )
        self.m_ribbonBar.SetActivePage( self.m_ribbonPageMain )
        self.m_ribbonPanelMain = rb.RibbonPanel( \
			self.m_ribbonPageMain, wx.ID_ANY, u"Main" , wx.NullBitmap , wx.DefaultPosition, \
			wx.DefaultSize, wx.lib.agw.ribbon.RIBBON_PANEL_DEFAULT_STYLE )
        self.m_ribbonButtonBarMain = rb.RibbonButtonBar( \
			self.m_ribbonPanelMain, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)
        self.m_ribbonButtonBarMain.AddSimpleButton( \
			ID_RIBBON_NEW, u"New", wx.Bitmap( u"new.png", wx.BITMAP_TYPE_ANY ), wx.EmptyString)
        self.m_ribbonButtonBarMain.AddSimpleButton( \
			ID_RIBBON_OPEN, u"Open", wx.Bitmap( u"open.png", wx.BITMAP_TYPE_ANY ), wx.EmptyString)
        self.m_ribbonButtonBarMain.AddSimpleButton( \
			ID_RIBBON_SAVE, u"Save", wx.Bitmap( u"save.png", wx.BITMAP_TYPE_ANY ), wx.EmptyString)
        self.m_ribbonButtonBarMain.AddSimpleButton( \
			ID_RIBBON_RUN, u"Run", wx.Bitmap( u"run.png", wx.BITMAP_TYPE_ANY ), wx.EmptyString)
        self.m_ribbonBar.Realize()

        MainSizer.Add( self.m_ribbonBar, 0, wx.ALL|wx.EXPAND, 5 )


        self.SetSizer( MainSizer )
        self.Layout()
        self.m_statusBar2 = self.CreateStatusBar( 1, wx.STB_SIZEGRIP, wx.ID_ANY )

        self.Centre( wx.BOTH )

        # Connect Events
        # self.m_ribbonButtonBarMain.Bind( wx.EVT_LEFT_DOWN, self.click_ribbon_click )
        self.m_ribbonButtonBarMain.Bind( rb.EVT_RIBBONBUTTONBAR_CLICKED, self.click_ribbon_click )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def click_ribbon_click( self, event ):
        buttonId = event.GetId()
        print('*',buttonId )
        if buttonId == ID_RIBBON_NEW :
            print('new')
        elif buttonId == ID_RIBBON_OPEN :
            print('open')
        elif buttonId == ID_RIBBON_SAVE :
            print('save')
        elif buttonId == ID_RIBBON_RUN :
            print('run')

app = wx.App(False)
 
frame = TestFrame(None)
frame.Show(True)
app.MainLoop()