iT邦幫忙

0

【PHP 抓取 EXCEL 的欄位值???】

我有一個 excel 如下圖所示

我用 PHPExcel 可以抓到裡面的值
但由於這個表的項目是有可能會變動的
橫、直的項目皆有可能
我希望做的時候可以是活的
就是依據表格的項目
新增或減少時
一樣可以抓到裡面的值
我希望可以抓到
A=>T_t1=>89.96
B=>T_t1=>90
.
.
.
.
H=>T_t7=>89.47
I=>T_t7=>89.89
.
.
.
I=>U_u5=>0.800

總之就是可以
【橫的項目】=>【直的項目】=>【分數】
這樣子抓到資料
並且隨著項目的變動
一樣可以成功抓取

請問怎麼做比較快呢??

我把 excel 放在這裡提供測試
https://skydrive.live.com/#cid=D174663ABFAE5C49&id=D174663ABFAE5C49!124

謝謝大家

雖然是假資料
不過可以猜測t1..t8和u1..u8不會重覆

所以建議可以忽略第一欄(T, U)
改成
A=>t1=>89.96
B=>t1=>90
.
.
.
.
H=>t7=>89.47
I=>t7=>89.89
.
.
.
I=>u5=>0.800


不知是否可行?
andyto202 iT邦研究生 4 級 ‧ 2012-08-12 13:42:29 檢舉
當然是可行的
只是程式碼要怎麼下呢??
因為如果把它弄成陣列後
只要有合併儲存格的地方
就會造成筆數不平均
忽略第一欄的意思是
忽略那些合併儲存格

陣列的索引值會如下
A=>t1=>89.96 (Row 2, Column 4)
B=>t1=>90 (Row 2, Column 5)
.
.
.
.
H=>t7=>89.47 (Row 8, Column 11)
I=>t7=>89.89 (Row 8, Column 12)
.
.
.
I=>u5=>0.800 (Row 15, Column 12)
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

4
wiseguy
iT邦超人 1 級 ‧ 2012-08-12 01:06:30

會抓第一行,其它就用迴圈抓就行了不是嗎?
如果 A~I 會增加,那就是第一層 while() 迴圈
如果 T,S,U 會增加,那就是 foreach() 迴圈
如果 T1~T8,U1~U5 會增加,那就再一層 while() 迴圈
虛擬碼大概就像醬

<pre class="c" name="code">while() /* 從 A 取到 I */
{
	foreach() /* T,S,U,... */
	{
		while() /* T1,T2,T3 */
		{

		}
	}
}
看更多先前的回應...收起先前的回應...
andyto202 iT邦研究生 4 級 ‧ 2012-08-12 07:15:46 檢舉

wiseguy兄
因為 excel 裡面它有合併儲存格
所以在抓取資料時會造成一些問題
例如
%=>U=>5
到時候抓資料時
其實那筆5是算在 u1 那列裡面的
u2之後就沒這個資料了

wiseguy iT邦超人 1 級 ‧ 2012-08-12 12:04:10 檢舉

那就把 foreach() 去除,完全忽略第一欄,直接看第二欄,也就是從 t1 開始。反正如果你需要第一欄,就從第二欄的值 (t1 的第一字元就是 t 了) 抓也一樣。

wiseguy iT邦超人 1 級 ‧ 2012-08-12 12:06:51 檢舉

抱歉,我的虛擬碼迴圈註解寫顛倒了,應該是:

<pre class="c" name="code">    while() /* T1,T2,T3,... */  
    {  
        while() /* 從 A 取到 I,... */  
        {  

        }  
    }  
andyto202 iT邦研究生 4 級 ‧ 2012-08-12 13:50:24 檢舉

可以請wiseguy兄
示範一下程式碼要如何寫呢??

andyto202 iT邦研究生 4 級 ‧ 2012-08-12 14:20:30 檢舉

因為那些項目都是我改過的
事實上它們都是中文字
所以沒有一個順序性
如果要做活的
就是程式依據它的欄位變動跟著變動
恐怕沒這麼容易

wiseguy iT邦超人 1 級 ‧ 2012-08-12 17:24:10 檢舉

你還真奇怪,別人要幫你解決問題,反而你自己先否定了這問題能解的可能性,那我們還幫不幫啊?
我覺得這一點都不難啊,難只難在你並沒有講清楚它的格式可能會怎麼變,你隱藏了資料原貌雖然是保密的原則,卻也增加我解題的困難度,我只好憑現在我所看到的敘述跟格式來猜。
即使是中文又有什麼難的?判斷第一欄每一個的合併欄位有幾列,就可以得到第二欄的個數。再從第一列去得到最長多少個欄位,一樣是三個迴圈就可以取得所有欄位了不是嗎?
試著自己寫寫看吧。自己解會比較有成就感的。

ted99tw iT邦高手 1 級 ‧ 2012-08-12 17:42:09 檢舉

wiseguy提到:
那我們還幫不幫啊?

好像某些行業為了測試滿意度,都會讓人來找碴....大人啊,這要列入您的年終考績,千萬要hold住....毆飛

0
rayford
iT邦新手 5 級 ‧ 2013-07-23 05:41:52

去年的發問現在的狀態還是"發問中"?我來試著回答。
1.第1列應該是固定的標題區,第2列以後是可變動的列數。

2.合併後的儲存格,會以左上角那一格做為該格的座標。
如果撇開你表格裡面自訂的ABCD不管,以Excel的格式來說,T這一格的座標就是A2。
因為它是最左邊,所以是A,最上面是第2列,所以這一格的座標是A2。

3.有了第2點規則,你就可以設定一個陣列,取得所有資料。

4.問題是如何設定這個陣列,如何設定元素名稱?
先提一下,你的圖會讓人誤解。
因為你的圖也用了ABCD...,讓跟Excel內建的欄位名稱混淆。
你的A實際上是D,左上角89.96這個儲存格,實際上是D2

<pre class="c" name="code">$highestRow = $sheet->getHighestRow();//取得最多列數
$highestColumn = $sheet->getHighestColumn(); // 取得最多欄數
for($r=2; $r<=$highestRow; $r++){ //對所有列做迴圈。 第1列是標題,從第2列開始
	//對同一列所有欄位做迴圈
    for($n=3; $n<$highestColumn; $n++){ 
	//要注意的是:橫座標從0開始,也就是A=0, B=1(Excel座標)。 而且這是從3開始,所以實際上是第4欄,也就是你的A欄(以Excel座標來講的話,應該是D欄)。
		
		$key3 = trim($sheet->getCellByColumnAndRow(0, $r)->getValue()); //T, S, U
		if(!empty($key3)){
			//如果key值不是空,把$lastKey3設成這個key值
			$lastKey3 = $key3;
		}
		else if(!empty($key3)){
			//如果key值是空,把$key3等於上一個不是空的那個key值.
			$key3 = $lastKey3;
		}
		
		$key2 = trim($sheet->getCellByColumnAndRow(1, $r)->getValue()); //t1, t2, s1, s2...
		//一樣要加上一段判斷,請複製後修改。
	   
		$key1 = chr($n+62); //要注意,這裡的內容不是key值,例如 89.96 是內容,你上面的A才是key值。
		//那要怎麼取得A呢?用chr這個函數可以把ASCII代碼轉成字元。 這樣當 $n==3 的時候,就會得到A這個字母。
		
		$value = trim($sheet->getCellByColumnAndRow($n, $r)->getValue());
		
		$array[$key1][$key2][$key3]= $value;
	}
}	

$array 就是你要的資料
概念大概是這樣,程式如果有錯請再自己修正。
可以參考:PHPExcel - 讀取Excel檔

我要發表回答

立即登入回答